about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristian Poveda <christianpoveda@protonmail.com>2019-07-04 01:45:29 -0500
committerChristian Poveda <christianpoveda@protonmail.com>2019-07-04 01:45:29 -0500
commite45bbaf48c9fb0439426967009d837f0fe4f74ce (patch)
treea887380eed192d6ea9b2f124574932bcc1297c34
parente32b8eb00a94274e680d1ae63c429d5b7db65e99 (diff)
parentb43eb4235ac43c822d903ad26ed806f34cc1a14a (diff)
downloadrust-e45bbaf48c9fb0439426967009d837f0fe4f74ce.tar.gz
rust-e45bbaf48c9fb0439426967009d837f0fe4f74ce.zip
Fix merge conflicts
-rw-r--r--.azure-pipelines/auto.yml15
-rw-r--r--.azure-pipelines/steps/run.yml7
-rw-r--r--.mailmap2
-rw-r--r--.travis.yml164
-rw-r--r--Cargo.lock26
-rw-r--r--RELEASES.md6
-rw-r--r--appveyor.yml109
-rw-r--r--src/bootstrap/builder/tests.rs2
-rw-r--r--src/bootstrap/flags.rs17
-rw-r--r--src/bootstrap/test.rs5
-rw-r--r--src/ci/docker/scripts/musl.sh2
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/codegen-options/index.md17
-rw-r--r--src/doc/rustc/src/profile-guided-optimization.md136
-rw-r--r--src/doc/rustdoc/src/documentation-tests.md13
-rw-r--r--src/doc/unstable-book/src/language-features/member-constraints.md29
-rw-r--r--src/doc/unstable-book/src/language-features/slice-patterns.md4
-rw-r--r--src/doc/unstable-book/src/language-features/type-alias-enum-variants.md36
-rwxr-xr-xsrc/etc/cpu-usage-over-time-plot.sh2
-rw-r--r--src/etc/gdb_load_rust_pretty_printers.py1
-rw-r--r--src/liballoc/boxed.rs22
-rw-r--r--src/liballoc/collections/binary_heap.rs5
-rw-r--r--src/liballoc/collections/btree/map.rs32
-rw-r--r--src/liballoc/collections/btree/set.rs7
-rw-r--r--src/liballoc/collections/linked_list.rs12
-rw-r--r--src/liballoc/collections/vec_deque.rs10
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/str.rs2
-rw-r--r--src/liballoc/string.rs5
-rw-r--r--src/liballoc/tests/vec.rs1
-rw-r--r--src/liballoc/vec.rs34
-rw-r--r--src/libcore/ascii.rs1
-rw-r--r--src/libcore/char/methods.rs6
-rw-r--r--src/libcore/convert.rs25
-rw-r--r--src/libcore/iter/traits/collect.rs2
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/marker.rs6
-rw-r--r--src/libcore/mem/mod.rs33
-rw-r--r--src/libcore/option.rs12
-rw-r--r--src/libcore/ptr/mod.rs32
-rw-r--r--src/libcore/raw.rs4
-rw-r--r--src/libcore/slice/mod.rs15
-rw-r--r--src/libcore/str/mod.rs47
-rw-r--r--src/libcore/tests/ascii.rs2
-rw-r--r--src/libcore/tests/fmt/mod.rs2
-rw-r--r--src/libcore/tests/pattern.rs2
-rw-r--r--src/libcore/tests/ptr.rs5
-rw-r--r--src/libcore/tests/slice.rs23
-rw-r--r--src/libproc_macro/bridge/buffer.rs2
-rw-r--r--src/libproc_macro/bridge/scoped_cell.rs2
-rw-r--r--src/libproc_macro/lib.rs1
-rw-r--r--src/librustc/cfg/construct.rs4
-rw-r--r--src/librustc/cfg/mod.rs2
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/dep_graph/graph.rs39
-rw-r--r--src/librustc/hir/check_attr.rs2
-rw-r--r--src/librustc/hir/lowering.rs28
-rw-r--r--src/librustc/hir/map/hir_id_validator.rs2
-rw-r--r--src/librustc/hir/map/mod.rs6
-rw-r--r--src/librustc/hir/mod.rs13
-rw-r--r--src/librustc/hir/print.rs2
-rw-r--r--src/librustc/hir/ptr.rs141
-rw-r--r--src/librustc/infer/canonical/mod.rs33
-rw-r--r--src/librustc/infer/canonical/query_response.rs46
-rw-r--r--src/librustc/infer/error_reporting/mod.rs22
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs341
-rw-r--r--src/librustc/infer/mod.rs18
-rw-r--r--src/librustc/infer/nll_relate/mod.rs2
-rw-r--r--src/librustc/infer/opaque_types/mod.rs516
-rw-r--r--src/librustc/infer/outlives/free_region_map.rs4
-rw-r--r--src/librustc/infer/outlives/obligations.rs2
-rw-r--r--src/librustc/infer/region_constraints/mod.rs77
-rw-r--r--src/librustc/infer/type_variable.rs2
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/middle/dead.rs4
-rw-r--r--src/librustc/middle/dependency_format.rs8
-rw-r--r--src/librustc/middle/expr_use_visitor.rs2
-rw-r--r--src/librustc/middle/intrinsicck.rs2
-rw-r--r--src/librustc/middle/lib_features.rs2
-rw-r--r--src/librustc/middle/liveness.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs8
-rw-r--r--src/librustc/middle/reachable.rs6
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/middle/resolve_lifetime.rs15
-rw-r--r--src/librustc/middle/stability.rs8
-rw-r--r--src/librustc/mir/interpret/error.rs8
-rw-r--r--src/librustc/mir/mod.rs12
-rw-r--r--src/librustc/query/mod.rs63
-rw-r--r--src/librustc/session/config.rs31
-rw-r--r--src/librustc/session/config/tests.rs4
-rw-r--r--src/librustc/session/mod.rs58
-rw-r--r--src/librustc/traits/coherence.rs10
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc/traits/fulfill.rs58
-rw-r--r--src/librustc/traits/mod.rs22
-rw-r--r--src/librustc/traits/object_safety.rs2
-rw-r--r--src/librustc/traits/project.rs9
-rw-r--r--src/librustc/traits/query/normalize.rs5
-rw-r--r--src/librustc/traits/query/type_op/custom.rs12
-rw-r--r--src/librustc/traits/query/type_op/mod.rs16
-rw-r--r--src/librustc/traits/select.rs59
-rw-r--r--src/librustc/traits/specialize/mod.rs10
-rw-r--r--src/librustc/traits/util.rs2
-rw-r--r--src/librustc/ty/erase_regions.rs6
-rw-r--r--src/librustc/ty/fold.rs4
-rw-r--r--src/librustc/ty/query/config.rs39
-rw-r--r--src/librustc/ty/query/mod.rs2
-rw-r--r--src/librustc/ty/query/on_disk_cache.rs32
-rw-r--r--src/librustc/ty/query/plumbing.rs124
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/structural_impls.rs34
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs4
-rw-r--r--src/librustc_borrowck/dataflow.rs6
-rw-r--r--src/librustc_codegen_llvm/attributes.rs4
-rw-r--r--src/librustc_codegen_llvm/back/archive.rs4
-rw-r--r--src/librustc_codegen_llvm/back/write.rs6
-rw-r--r--src/librustc_codegen_llvm/base.rs4
-rw-r--r--src/librustc_codegen_llvm/builder.rs2
-rw-r--r--src/librustc_codegen_llvm/lib.rs3
-rw-r--r--src/librustc_codegen_ssa/back/command.rs2
-rw-r--r--src/librustc_codegen_ssa/back/link.rs14
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs30
-rw-r--r--src/librustc_codegen_ssa/back/write.rs13
-rw-r--r--src/librustc_codegen_ssa/base.rs2
-rw-r--r--src/librustc_codegen_ssa/debuginfo/mod.rs2
-rw-r--r--src/librustc_codegen_ssa/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/builder.rs2
-rw-r--r--src/librustc_codegen_utils/symbol_names_test.rs2
-rw-r--r--src/librustc_data_structures/binary_search_util/mod.rs49
-rw-r--r--src/librustc_data_structures/binary_search_util/test.rs23
-rw-r--r--src/librustc_data_structures/bit_set.rs4
-rw-r--r--src/librustc_data_structures/fingerprint.rs2
-rw-r--r--src/librustc_data_structures/graph/implementation/mod.rs6
-rw-r--r--src/librustc_data_structures/graph/iterate/mod.rs36
-rw-r--r--src/librustc_data_structures/graph/mod.rs24
-rw-r--r--src/librustc_data_structures/graph/reference.rs8
-rw-r--r--src/librustc_data_structures/graph/scc/mod.rs46
-rw-r--r--src/librustc_data_structures/graph/test.rs8
-rw-r--r--src/librustc_data_structures/graph/vec_graph/mod.rs113
-rw-r--r--src/librustc_data_structures/graph/vec_graph/test.rs51
-rw-r--r--src/librustc_data_structures/indexed_vec.rs15
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_data_structures/transitive_relation.rs4
-rw-r--r--src/librustc_driver/pretty.rs20
-rw-r--r--src/librustc_errors/emitter.rs2
-rw-r--r--src/librustc_errors/lib.rs84
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs2
-rw-r--r--src/librustc_incremental/assert_module_sources.rs2
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs2
-rw-r--r--src/librustc_incremental/persist/load.rs4
-rw-r--r--src/librustc_incremental/persist/save.rs2
-rw-r--r--src/librustc_interface/passes.rs6
-rw-r--r--src/librustc_interface/proc_macro_decls.rs4
-rw-r--r--src/librustc_interface/util.rs6
-rw-r--r--src/librustc_lint/lib.rs2
-rw-r--r--src/librustc_lint/unused.rs48
-rw-r--r--src/librustc_macros/src/lib.rs2
-rw-r--r--src/librustc_macros/src/query.rs112
-rw-r--r--src/librustc_metadata/creader.rs2
-rw-r--r--src/librustc_metadata/cstore_impl.rs4
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_metadata/foreign_modules.rs2
-rw-r--r--src/librustc_metadata/link_args.rs2
-rw-r--r--src/librustc_metadata/native_libs.rs2
-rw-r--r--src/librustc_mir/borrow_check/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/constraints/graph.rs32
-rw-r--r--src/librustc_mir/borrow_check/nll/constraints/mod.rs37
-rw-r--r--src/librustc_mir/borrow_check/nll/member_constraints.rs235
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs3
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs41
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs470
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/values.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs29
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs8
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs38
-rw-r--r--src/librustc_mir/borrow_check/path_utils.rs2
-rw-r--r--src/librustc_mir/build/expr/category.rs2
-rw-r--r--src/librustc_mir/build/matches/simplify.rs2
-rw-r--r--src/librustc_mir/build/matches/test.rs2
-rw-r--r--src/librustc_mir/build/mod.rs10
-rw-r--r--src/librustc_mir/const_eval.rs28
-rw-r--r--src/librustc_mir/dataflow/at_location.rs32
-rw-r--r--src/librustc_mir/dataflow/impls/borrowed_locals.rs2
-rw-r--r--src/librustc_mir/dataflow/impls/storage_liveness.rs130
-rw-r--r--src/librustc_mir/dataflow/mod.rs115
-rw-r--r--src/librustc_mir/hair/cx/to_ref.rs2
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs2
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs6
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs2
-rw-r--r--src/librustc_mir/interpret/cast.rs30
-rw-r--r--src/librustc_mir/interpret/eval_context.rs14
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs4
-rw-r--r--src/librustc_mir/interpret/machine.rs20
-rw-r--r--src/librustc_mir/interpret/memory.rs15
-rw-r--r--src/librustc_mir/interpret/mod.rs2
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/interpret/operator.rs6
-rw-r--r--src/librustc_mir/interpret/place.rs6
-rw-r--r--src/librustc_mir/interpret/step.rs6
-rw-r--r--src/librustc_mir/interpret/terminator.rs4
-rw-r--r--src/librustc_mir/interpret/traits.rs4
-rw-r--r--src/librustc_mir/interpret/validity.rs8
-rw-r--r--src/librustc_mir/interpret/visitor.rs24
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/monomorphize/collector.rs14
-rw-r--r--src/librustc_mir/monomorphize/partitioning.rs6
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/add_retag.rs4
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs14
-rw-r--r--src/librustc_mir/transform/const_prop.rs6
-rw-r--r--src/librustc_mir/transform/dump_mir.rs4
-rw-r--r--src/librustc_mir/transform/generator.rs74
-rw-r--r--src/librustc_mir/transform/mod.rs12
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/transform/simplify.rs2
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs2
-rw-r--r--src/librustc_mir/util/def_use.rs2
-rw-r--r--src/librustc_mir/util/graphviz.rs4
-rw-r--r--src/librustc_mir/util/liveness.rs29
-rw-r--r--src/librustc_mir/util/mod.rs2
-rw-r--r--src/librustc_passes/ast_validation.rs7
-rw-r--r--src/librustc_passes/hir_stats.rs2
-rw-r--r--src/librustc_passes/layout_test.rs2
-rw-r--r--src/librustc_passes/loops.rs2
-rw-r--r--src/librustc_passes/rvalue_promotion.rs4
-rw-r--r--src/librustc_plugin/build.rs4
-rw-r--r--src/librustc_plugin/registry.rs7
-rw-r--r--src/librustc_privacy/lib.rs20
-rw-r--r--src/librustc_resolve/lib.rs9
-rw-r--r--src/librustc_resolve/macros.rs9
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_target/spec/windows_msvc_base.rs4
-rw-r--r--src/librustc_traits/chalk_context/mod.rs5
-rw-r--r--src/librustc_traits/chalk_context/program_clauses/primitive.rs16
-rw-r--r--src/librustc_traits/dropck_outlives.rs8
-rw-r--r--src/librustc_traits/lowering/environment.rs2
-rw-r--r--src/librustc_traits/lowering/mod.rs20
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/_match.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/expr.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/mod.rs3
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs66
-rw-r--r--src/librustc_typeck/check/wfcheck.rs43
-rw-r--r--src/librustc_typeck/check/writeback.rs35
-rw-r--r--src/librustc_typeck/check_unused.rs4
-rw-r--r--src/librustc_typeck/coherence/builtin.rs8
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs41
-rw-r--r--src/librustc_typeck/coherence/inherent_impls_overlap.rs2
-rw-r--r--src/librustc_typeck/coherence/mod.rs8
-rw-r--r--src/librustc_typeck/coherence/orphan.rs2
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs2
-rw-r--r--src/librustc_typeck/collect.rs72
-rw-r--r--src/librustc_typeck/impl_wf_check.rs10
-rw-r--r--src/librustc_typeck/lib.rs26
-rw-r--r--src/librustc_typeck/outlives/mod.rs12
-rw-r--r--src/librustc_typeck/outlives/test.rs2
-rw-r--r--src/librustc_typeck/outlives/utils.rs2
-rw-r--r--src/librustc_typeck/variance/mod.rs4
-rw-r--r--src/librustc_typeck/variance/test.rs2
-rw-r--r--src/librustdoc/clean/cfg.rs2
-rw-r--r--src/librustdoc/clean/mod.rs115
-rw-r--r--src/librustdoc/clean/simplify.rs2
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/doctree.rs4
-rw-r--r--src/librustdoc/html/format.rs3
-rw-r--r--src/librustdoc/html/item_type.rs1
-rw-r--r--src/librustdoc/html/render.rs5
-rw-r--r--src/librustdoc/lib.rs3
-rw-r--r--src/librustdoc/passes/collapse_docs.rs4
-rw-r--r--src/librustdoc/test.rs13
-rw-r--r--src/libstd/collections/hash/map.rs6
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/panic.rs6
-rw-r--r--src/libstd/panicking.rs6
-rw-r--r--src/libstd/process.rs27
-rw-r--r--src/libstd/sync/mpsc/sync.rs2
-rw-r--r--src/libstd/sys/unix/condvar.rs12
-rw-r--r--src/libstd/sys/unix/ext/net.rs11
-rw-r--r--src/libstd/sys/unix/mutex.rs24
-rw-r--r--src/libstd/sys/unix/process/process_common.rs14
-rw-r--r--src/libstd/sys/unix/process/process_unix.rs58
-rw-r--r--src/libstd/sys/windows/pipe.rs2
-rw-r--r--src/libsyntax/attr/mod.rs6
-rw-r--r--src/libsyntax/ext/expand.rs47
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs2
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs2
-rw-r--r--src/libsyntax/feature_gate.rs12
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/lexer/mod.rs22
-rw-r--r--src/libsyntax/parse/lexer/unicode_chars.rs117
-rw-r--r--src/libsyntax/parse/parser.rs244
-rw-r--r--src/libsyntax/ptr.rs4
-rw-r--r--src/libsyntax/test.rs4
-rw-r--r--src/libsyntax/util/parser_testing.rs2
-rw-r--r--src/libsyntax_ext/assert.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs4
-rw-r--r--src/libsyntax_ext/deriving/generic/ty.rs6
-rw-r--r--src/libsyntax_pos/symbol.rs4
-rw-r--r--src/libunwind/build.rs8
-rw-r--r--src/libunwind/libunwind.rs10
-rw-r--r--src/test/codegen/pgo-instrumentation.rs4
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs2
-rw-r--r--src/test/incremental/change_add_field/struct_point.rs2
-rw-r--r--src/test/incremental/change_crate_dep_kind.rs2
-rw-r--r--src/test/incremental/change_private_fn/struct_point.rs2
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs2
-rw-r--r--src/test/incremental/change_private_impl_method/struct_point.rs2
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs2
-rw-r--r--src/test/incremental/change_pub_inherent_method_body/struct_point.rs2
-rw-r--r--src/test/incremental/change_pub_inherent_method_sig/struct_point.rs2
-rw-r--r--src/test/incremental/hashes/call_expressions.rs2
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs2
-rw-r--r--src/test/incremental/hashes/consts.rs2
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs2
-rw-r--r--src/test/incremental/hashes/enum_defs.rs2
-rw-r--r--src/test/incremental/hashes/exported_vs_not.rs2
-rw-r--r--src/test/incremental/hashes/extern_mods.rs2
-rw-r--r--src/test/incremental/hashes/for_loops.rs2
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs2
-rw-r--r--src/test/incremental/hashes/if_expressions.rs2
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs2
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs2
-rw-r--r--src/test/incremental/hashes/inline_asm.rs2
-rw-r--r--src/test/incremental/hashes/let_expressions.rs2
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs2
-rw-r--r--src/test/incremental/hashes/match_expressions.rs2
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs2
-rw-r--r--src/test/incremental/hashes/statics.rs2
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs2
-rw-r--r--src/test/incremental/hashes/struct_defs.rs2
-rw-r--r--src/test/incremental/hashes/trait_defs.rs2
-rw-r--r--src/test/incremental/hashes/trait_impls.rs2
-rw-r--r--src/test/incremental/hashes/type_defs.rs2
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs2
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs2
-rw-r--r--src/test/incremental/hashes/while_loops.rs2
-rw-r--r--src/test/incremental/ich_nested_items.rs2
-rw-r--r--src/test/incremental/incremental_proc_macro.rs2
-rw-r--r--src/test/incremental/issue-42602.rs2
-rw-r--r--src/test/incremental/issue-49595/issue-49595.rs2
-rw-r--r--src/test/incremental/issue-59523-on-implemented-is-not-unused.rs2
-rw-r--r--src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs2
-rw-r--r--src/test/incremental/krate-inherent.rs2
-rw-r--r--src/test/incremental/macro_export.rs2
-rw-r--r--src/test/incremental/remove_source_file/main.rs2
-rw-r--r--src/test/incremental/string_constant.rs2
-rw-r--r--src/test/incremental/thinlto/cgu_invalidated_via_import.rs2
-rw-r--r--src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs2
-rw-r--r--src/test/incremental/warnings-reemitted.rs2
-rw-r--r--src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile8
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-lto/Makefile2
-rw-r--r--src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile2
-rw-r--r--src/test/run-make-fulldeps/pgo-gen/Makefile2
-rw-r--r--src/test/run-make-fulldeps/pgo-use/Makefile4
-rw-r--r--src/test/run-pass/async-await/async-fn-size-moved-locals.rs98
-rw-r--r--src/test/run-pass/async-await/async-fn-size.rs (renamed from src/test/run-pass/async-fn-size.rs)4
-rw-r--r--src/test/run-pass/async-await/issue-60709.rs28
-rw-r--r--src/test/run-pass/command-uid-gid.rs26
-rw-r--r--src/test/run-pass/generator/size-moved-locals.rs62
-rw-r--r--src/test/run-pass/issues/issue-30530.rs4
-rw-r--r--src/test/run-pass/packed/packed-with-inference-vars-issue-61402.rs21
-rw-r--r--src/test/run-pass/panics/panic-handler-flail-wildly.rs2
-rw-r--r--src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs2
-rw-r--r--src/test/run-pass/type-alias-enum-variants-2.rs30
-rw-r--r--src/test/run-pass/type-alias-enum-variants.rs30
-rw-r--r--src/test/rustdoc-ui/cfg-test.rs9
-rw-r--r--src/test/rustdoc-ui/cfg-test.stdout2
-rw-r--r--src/test/rustdoc-ui/coverage/basic.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/empty.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/enums.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/exotic.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/private.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/statics-consts.rs2
-rw-r--r--src/test/rustdoc-ui/coverage/traits.rs2
-rw-r--r--src/test/rustdoc-ui/deprecated-attrs.rs2
-rw-r--r--src/test/rustdoc-ui/intra-links-warning-crlf.rs2
-rw-r--r--src/test/rustdoc-ui/intra-links-warning.rs2
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.rs2
-rw-r--r--src/test/rustdoc-ui/issue-58473-2.rs2
-rw-r--r--src/test/rustdoc-ui/issue-58473.rs2
-rw-r--r--src/test/rustdoc-ui/unused.rs2
-rw-r--r--src/test/rustdoc/process-termination.rs12
-rw-r--r--src/test/ui/anon-params-deprecated.fixed2
-rw-r--r--src/test/ui/anon-params-deprecated.rs2
-rw-r--r--src/test/ui/associated-const/associated-const-trait-bound.rs2
-rw-r--r--src/test/ui/associated-type-bounds/entails-sized-object-safety.rs2
-rw-r--r--src/test/ui/associated-type-bounds/trait-params.rs2
-rw-r--r--src/test/ui/associated-type-bounds/type-alias.rs2
-rw-r--r--src/test/ui/async-await/async-await.rs13
-rw-r--r--src/test/ui/async-await/async-fn-multiple-lifetimes.rs19
-rw-r--r--src/test/ui/async-await/async-fn-multiple-lifetimes.stderr20
-rw-r--r--src/test/ui/async-await/async-fn-send-uses-nonsend.rs2
-rw-r--r--src/test/ui/async-await/async-matches-expr.rs2
-rw-r--r--src/test/ui/async-await/async-with-closure.rs2
-rw-r--r--src/test/ui/async-await/edition-deny-async-fns-2015.rs6
-rw-r--r--src/test/ui/async-await/edition-deny-async-fns-2015.stderr28
-rw-r--r--src/test/ui/async-await/generics-and-bounds.rs2
-rw-r--r--src/test/ui/async-await/issue-61793.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-53249.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-54974.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-55324.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-58885.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-59001.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-60518.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-60655-latebound-regions.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-60674.rs2
-rw-r--r--src/test/ui/async-await/issues/issue-61986.rs2
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/elided.rs12
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs14
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/hrtb.rs17
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/named.rs12
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/partial-relation.rs15
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs18
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs18
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr10
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr15
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs27
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr11
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-ref.rs46
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr37
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/variance.rs18
-rw-r--r--src/test/ui/async-await/no-unsafe-async.rs11
-rw-r--r--src/test/ui/async-await/no-unsafe-async.stderr14
-rw-r--r--src/test/ui/attributes/attr-before-view-item.rs2
-rw-r--r--src/test/ui/attributes/attr-before-view-item2.rs2
-rw-r--r--src/test/ui/attributes/attr-mix-new.rs2
-rw-r--r--src/test/ui/attributes/class-attributes-1.rs2
-rw-r--r--src/test/ui/attributes/class-attributes-2.rs2
-rw-r--r--src/test/ui/attributes/item-attributes.rs2
-rw-r--r--src/test/ui/attributes/method-attributes.rs2
-rw-r--r--src/test/ui/attributes/variant-attributes.rs2
-rw-r--r--src/test/ui/bastion-of-the-turbofish.rs2
-rw-r--r--src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs2
-rw-r--r--src/test/ui/check_match/issue-43253.rs2
-rw-r--r--src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs2
-rw-r--r--src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs2
-rw-r--r--src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs2
-rw-r--r--src/test/ui/closure-expected-type/issue-24421.rs2
-rw-r--r--src/test/ui/closure_promotion.rs2
-rw-r--r--src/test/ui/codemap_tests/unicode_3.rs2
-rw-r--r--src/test/ui/coercion/coerce-issue-49593-box-never.rs2
-rw-r--r--src/test/ui/coherence/coherence-subtyping.rs2
-rw-r--r--src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs2
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-false.rs2
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-multi-true.rs2
-rw-r--r--src/test/ui/const-generics/cannot-infer-type-for-const-param.rs2
-rw-r--r--src/test/ui/const-generics/issue-60818-struct-constructors.rs2
-rw-r--r--src/test/ui/consts/const-block-non-item-statement.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_prop_errors.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_signed_pat.rs2
-rw-r--r--src/test/ui/consts/const-eval/double_check.rs2
-rw-r--r--src/test/ui/consts/const-eval/double_promotion.rs2
-rw-r--r--src/test/ui/consts/const-eval/duration_conversion.rs2
-rw-r--r--src/test/ui/consts/const-eval/extern_fat_pointer.rs2
-rw-r--r--src/test/ui/consts/const-eval/ice-generic-assoc-const.rs2
-rw-r--r--src/test/ui/consts/const-eval/ice-packed.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-47971.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-50706.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-51300.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-53157.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-53401.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-55541.rs2
-rw-r--r--src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs2
-rw-r--r--src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs2
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.rs24
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.stderr42
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err.rs2
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err_bin.rs2
-rw-r--r--src/test/ui/consts/const-eval/simple_with_undef.rs2
-rw-r--r--src/test/ui/consts/const-eval/valid-const.rs2
-rw-r--r--src/test/ui/consts/const-eval/zst_operand_eval.rs2
-rw-r--r--src/test/ui/consts/const-expr-addr-operator.rs2
-rw-r--r--src/test/ui/consts/const-fn-destructuring-arg.rs2
-rw-r--r--src/test/ui/consts/const-nonzero.rs2
-rw-r--r--src/test/ui/consts/const-pattern-not-const-evaluable.rs2
-rw-r--r--src/test/ui/consts/const-validation-fail-55455.rs2
-rw-r--r--src/test/ui/consts/const_fn_return_nested_fn_ptr.rs2
-rw-r--r--src/test/ui/consts/const_let_assign.rs2
-rw-r--r--src/test/ui/consts/const_let_assign2.rs2
-rw-r--r--src/test/ui/consts/const_let_eq_float.rs2
-rw-r--r--src/test/ui/consts/const_let_irrefutable.rs2
-rw-r--r--src/test/ui/consts/drop_none.rs2
-rw-r--r--src/test/ui/consts/int_ptr_for_zst_slices.rs2
-rw-r--r--src/test/ui/consts/invalid_promotion.rs2
-rw-r--r--src/test/ui/consts/issue-62045.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs2
-rw-r--r--src/test/ui/consts/promote_evaluation_unused_result.rs2
-rw-r--r--src/test/ui/consts/promote_fn_calls.rs2
-rw-r--r--src/test/ui/consts/promote_fn_calls_std.rs2
-rw-r--r--src/test/ui/consts/promoted-validation-55454.rs2
-rw-r--r--src/test/ui/consts/promoted_regression.rs2
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref.rs2
-rw-r--r--src/test/ui/consts/std/slice.rs2
-rw-r--r--src/test/ui/consts/underscore_const_names.rs2
-rw-r--r--src/test/ui/consts/union_constant.rs2
-rw-r--r--src/test/ui/dead-code-tuple-struct-field.rs2
-rw-r--r--src/test/ui/deprecation/atomic_initializers.fixed2
-rw-r--r--src/test/ui/deprecation/atomic_initializers.rs2
-rw-r--r--src/test/ui/deprecation/derive_on_deprecated.rs2
-rw-r--r--src/test/ui/deprecation/derive_on_deprecated_forbidden.rs2
-rw-r--r--src/test/ui/derive-uninhabited-enum-38885.rs2
-rw-r--r--src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs2
-rw-r--r--src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs2
-rw-r--r--src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs2
-rw-r--r--src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs2
-rw-r--r--src/test/ui/editions/edition-extern-crate-allowed.rs2
-rw-r--r--src/test/ui/editions/edition-feature-ok.rs2
-rw-r--r--src/test/ui/editions/edition-feature-redundant.rs2
-rw-r--r--src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs2
-rw-r--r--src/test/ui/editions/edition-keywords-2015-2015-expansion.rs2
-rw-r--r--src/test/ui/editions/edition-keywords-2018-2015-expansion.rs2
-rw-r--r--src/test/ui/emit-artifact-notifications.rs4
-rw-r--r--src/test/ui/error-codes/E0705.rs2
-rw-r--r--src/test/ui/existential_types/bound_reduction.rs2
-rw-r--r--src/test/ui/existential_types/cross_crate_ice.rs2
-rw-r--r--src/test/ui/existential_types/cross_crate_ice2.rs2
-rw-r--r--src/test/ui/existential_types/different_defining_uses_never_type2.rs2
-rw-r--r--src/test/ui/existential_types/existential-associated-type.rs2
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use10.rs2
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use7.rs2
-rw-r--r--src/test/ui/existential_types/generic_lifetime_param.rs2
-rw-r--r--src/test/ui/existential_types/nested_existential_types.rs2
-rw-r--r--src/test/ui/existential_types/private_unused.rs2
-rw-r--r--src/test/ui/explain.rs2
-rw-r--r--src/test/ui/extern-prelude.rs2
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-const-indexing.rs2
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-member-constraints.stderr10
-rw-r--r--src/test/ui/feature-gates/feature-gate-slice-patterns.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs19
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr34
-rw-r--r--src/test/ui/fn_must_use.rs2
-rw-r--r--src/test/ui/generator/issue-53548-1.rs2
-rw-r--r--src/test/ui/generator/issue-53548.rs2
-rw-r--r--src/test/ui/generic/generic-param-attrs.rs2
-rw-r--r--src/test/ui/hello_world/main.rs2
-rw-r--r--src/test/ui/hygiene/dollar-crate-modern.rs2
-rw-r--r--src/test/ui/hygiene/local_inner_macros.rs2
-rw-r--r--src/test/ui/hygiene/transparent-basic.rs2
-rw-r--r--src/test/ui/if/if-let.rs2
-rw-r--r--src/test/ui/impl-header-lifetime-elision/inherent-impl.rs2
-rw-r--r--src/test/ui/impl-trait/associated-existential-type-generic-trait.rs2
-rw-r--r--src/test/ui/impl-trait/associated-existential-type-trivial.rs2
-rw-r--r--src/test/ui/impl-trait/associated-existential-type.rs2
-rw-r--r--src/test/ui/impl-trait/can-return-unconstrained-closure.rs2
-rw-r--r--src/test/ui/impl-trait/deprecated_annotation.rs2
-rw-r--r--src/test/ui/impl-trait/existential-minimal.rs2
-rw-r--r--src/test/ui/impl-trait/existential_type_in_fn_body.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-42479.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-49376.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-52128.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes.rs2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs22
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr12
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs54
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr19
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs29
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-existential.rs32
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs29
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs46
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr9
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs38
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr21
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr9
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs41
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr21
-rw-r--r--src/test/ui/impl-trait/needs_least_region_or_bound.rs16
-rw-r--r--src/test/ui/impl-trait/needs_least_region_or_bound.stderr8
-rw-r--r--src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs2
-rw-r--r--src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs2
-rw-r--r--src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs2
-rw-r--r--src/test/ui/imports/extern-prelude-extern-crate-cfg.rs2
-rw-r--r--src/test/ui/imports/extern-prelude-extern-crate-pass.rs2
-rw-r--r--src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs2
-rw-r--r--src/test/ui/imports/gensymed.rs2
-rw-r--r--src/test/ui/imports/issue-53140.rs2
-rw-r--r--src/test/ui/imports/issue-55811.rs2
-rw-r--r--src/test/ui/imports/issue-56263.rs2
-rw-r--r--src/test/ui/imports/local-modularized-tricky-pass.rs2
-rw-r--r--src/test/ui/imports/local-modularized.rs2
-rw-r--r--src/test/ui/inference/inference-variable-behind-raw-pointer.rs2
-rw-r--r--src/test/ui/issue-53912.rs2
-rw-r--r--src/test/ui/issues/issue-10396.rs2
-rw-r--r--src/test/ui/issues/issue-10456.rs2
-rw-r--r--src/test/ui/issues/issue-10536.rs8
-rw-r--r--src/test/ui/issues/issue-10536.stderr38
-rw-r--r--src/test/ui/issues/issue-10763.rs2
-rw-r--r--src/test/ui/issues/issue-10853.rs2
-rw-r--r--src/test/ui/issues/issue-10902.rs2
-rw-r--r--src/test/ui/issues/issue-11384.rs2
-rw-r--r--src/test/ui/issues/issue-11592.rs2
-rw-r--r--src/test/ui/issues/issue-11612.rs2
-rw-r--r--src/test/ui/issues/issue-11869.rs2
-rw-r--r--src/test/ui/issues/issue-1251.rs2
-rw-r--r--src/test/ui/issues/issue-12729.rs2
-rw-r--r--src/test/ui/issues/issue-13105.rs2
-rw-r--r--src/test/ui/issues/issue-13167.rs2
-rw-r--r--src/test/ui/issues/issue-13214.rs2
-rw-r--r--src/test/ui/issues/issue-13405.rs2
-rw-r--r--src/test/ui/issues/issue-13703.rs2
-rw-r--r--src/test/ui/issues/issue-13775.rs2
-rw-r--r--src/test/ui/issues/issue-13837.rs2
-rw-r--r--src/test/ui/issues/issue-14082.rs2
-rw-r--r--src/test/ui/issues/issue-14254.rs2
-rw-r--r--src/test/ui/issues/issue-14330.rs2
-rw-r--r--src/test/ui/issues/issue-14837.rs2
-rw-r--r--src/test/ui/issues/issue-14901.rs2
-rw-r--r--src/test/ui/issues/issue-14933.rs2
-rw-r--r--src/test/ui/issues/issue-14936.rs2
-rw-r--r--src/test/ui/issues/issue-14959.rs2
-rw-r--r--src/test/ui/issues/issue-15108.rs2
-rw-r--r--src/test/ui/issues/issue-15261.rs2
-rw-r--r--src/test/ui/issues/issue-15689-2.rs2
-rw-r--r--src/test/ui/issues/issue-15735.rs2
-rw-r--r--src/test/ui/issues/issue-16596.rs2
-rw-r--r--src/test/ui/issues/issue-16668.rs2
-rw-r--r--src/test/ui/issues/issue-17121.rs2
-rw-r--r--src/test/ui/issues/issue-17263.rs2
-rw-r--r--src/test/ui/issues/issue-17336.rs2
-rw-r--r--src/test/ui/issues/issue-17450.rs2
-rw-r--r--src/test/ui/issues/issue-17718-const-destructors.rs2
-rw-r--r--src/test/ui/issues/issue-17732.rs2
-rw-r--r--src/test/ui/issues/issue-17746.rs2
-rw-r--r--src/test/ui/issues/issue-17904.rs2
-rw-r--r--src/test/ui/issues/issue-18083.rs2
-rw-r--r--src/test/ui/issues/issue-18088.rs2
-rw-r--r--src/test/ui/issues/issue-18188.rs2
-rw-r--r--src/test/ui/issues/issue-1821.rs2
-rw-r--r--src/test/ui/issues/issue-18446-2.rs2
-rw-r--r--src/test/ui/issues/issue-1866.rs2
-rw-r--r--src/test/ui/issues/issue-18738.rs2
-rw-r--r--src/test/ui/issues/issue-18809.rs2
-rw-r--r--src/test/ui/issues/issue-18906.rs2
-rw-r--r--src/test/ui/issues/issue-18988.rs2
-rw-r--r--src/test/ui/issues/issue-19037.rs2
-rw-r--r--src/test/ui/issues/issue-19081.rs2
-rw-r--r--src/test/ui/issues/issue-19097.rs2
-rw-r--r--src/test/ui/issues/issue-19098.rs2
-rw-r--r--src/test/ui/issues/issue-19102.rs2
-rw-r--r--src/test/ui/issues/issue-19129-1.rs2
-rw-r--r--src/test/ui/issues/issue-19129-2.rs2
-rw-r--r--src/test/ui/issues/issue-19398.rs2
-rw-r--r--src/test/ui/issues/issue-19404.rs2
-rw-r--r--src/test/ui/issues/issue-19479.rs2
-rw-r--r--src/test/ui/issues/issue-19631.rs2
-rw-r--r--src/test/ui/issues/issue-19632.rs2
-rw-r--r--src/test/ui/issues/issue-19850.rs2
-rw-r--r--src/test/ui/issues/issue-19982.rs2
-rw-r--r--src/test/ui/issues/issue-20009.rs2
-rw-r--r--src/test/ui/issues/issue-20091.rs2
-rw-r--r--src/test/ui/issues/issue-20186.rs2
-rw-r--r--src/test/ui/issues/issue-20396.rs2
-rw-r--r--src/test/ui/issues/issue-20414.rs2
-rw-r--r--src/test/ui/issues/issue-20454.rs2
-rw-r--r--src/test/ui/issues/issue-2063-resource.rs2
-rw-r--r--src/test/ui/issues/issue-20644.rs2
-rw-r--r--src/test/ui/issues/issue-20763-1.rs2
-rw-r--r--src/test/ui/issues/issue-20763-2.rs2
-rw-r--r--src/test/ui/issues/issue-20797.rs2
-rw-r--r--src/test/ui/issues/issue-20825-2.rs2
-rw-r--r--src/test/ui/issues/issue-21140.rs2
-rw-r--r--src/test/ui/issues/issue-21174-2.rs2
-rw-r--r--src/test/ui/issues/issue-21245.rs2
-rw-r--r--src/test/ui/issues/issue-21363.rs2
-rw-r--r--src/test/ui/issues/issue-21402.rs2
-rw-r--r--src/test/ui/issues/issue-21520.rs2
-rw-r--r--src/test/ui/issues/issue-21562.rs2
-rw-r--r--src/test/ui/issues/issue-21622.rs2
-rw-r--r--src/test/ui/issues/issue-21634.rs2
-rw-r--r--src/test/ui/issues/issue-21726.rs2
-rw-r--r--src/test/ui/issues/issue-21891.rs2
-rw-r--r--src/test/ui/issues/issue-22066.rs2
-rw-r--r--src/test/ui/issues/issue-22356.rs2
-rw-r--r--src/test/ui/issues/issue-22375.rs2
-rw-r--r--src/test/ui/issues/issue-22471.rs2
-rw-r--r--src/test/ui/issues/issue-22777.rs2
-rw-r--r--src/test/ui/issues/issue-22781.rs2
-rw-r--r--src/test/ui/issues/issue-22814.rs2
-rw-r--r--src/test/ui/issues/issue-22894.rs2
-rw-r--r--src/test/ui/issues/issue-2311-2.rs2
-rw-r--r--src/test/ui/issues/issue-2311.rs2
-rw-r--r--src/test/ui/issues/issue-2312.rs2
-rw-r--r--src/test/ui/issues/issue-23406.rs2
-rw-r--r--src/test/ui/issues/issue-23442.rs2
-rw-r--r--src/test/ui/issues/issue-23477.rs2
-rw-r--r--src/test/ui/issues/issue-23550.rs2
-rw-r--r--src/test/ui/issues/issue-23649-3.rs2
-rw-r--r--src/test/ui/issues/issue-24085.rs2
-rw-r--r--src/test/ui/issues/issue-24161.rs2
-rw-r--r--src/test/ui/issues/issue-24227.rs2
-rw-r--r--src/test/ui/issues/issue-24338.rs2
-rw-r--r--src/test/ui/issues/issue-24389.rs2
-rw-r--r--src/test/ui/issues/issue-24434.rs2
-rw-r--r--src/test/ui/issues/issue-2487-a.rs2
-rw-r--r--src/test/ui/issues/issue-2502.rs2
-rw-r--r--src/test/ui/issues/issue-25180.rs2
-rw-r--r--src/test/ui/issues/issue-25394.rs2
-rw-r--r--src/test/ui/issues/issue-25579.rs2
-rw-r--r--src/test/ui/issues/issue-26095.rs2
-rw-r--r--src/test/ui/issues/issue-2611-3.rs2
-rw-r--r--src/test/ui/issues/issue-26205.rs2
-rw-r--r--src/test/ui/issues/issue-26646.rs2
-rw-r--r--src/test/ui/issues/issue-26997.rs2
-rw-r--r--src/test/ui/issues/issue-27105.rs2
-rw-r--r--src/test/ui/issues/issue-27281.rs2
-rw-r--r--src/test/ui/issues/issue-2748-a.rs2
-rw-r--r--src/test/ui/issues/issue-27583.rs2
-rw-r--r--src/test/ui/issues/issue-27889.rs2
-rw-r--r--src/test/ui/issues/issue-2804-2.rs2
-rw-r--r--src/test/ui/issues/issue-28279.rs2
-rw-r--r--src/test/ui/issues/issue-28561.rs2
-rw-r--r--src/test/ui/issues/issue-28600.rs2
-rw-r--r--src/test/ui/issues/issue-28822.rs2
-rw-r--r--src/test/ui/issues/issue-28871.rs2
-rw-r--r--src/test/ui/issues/issue-28936.rs2
-rw-r--r--src/test/ui/issues/issue-28999.rs2
-rw-r--r--src/test/ui/issues/issue-29030.rs2
-rw-r--r--src/test/ui/issues/issue-29037.rs2
-rw-r--r--src/test/ui/issues/issue-2904.rs2
-rw-r--r--src/test/ui/issues/issue-29048.rs2
-rw-r--r--src/test/ui/issues/issue-29071.rs2
-rw-r--r--src/test/ui/issues/issue-29276.rs2
-rw-r--r--src/test/ui/issues/issue-29516.rs2
-rw-r--r--src/test/ui/issues/issue-29540.rs2
-rw-r--r--src/test/ui/issues/issue-29710.rs2
-rw-r--r--src/test/ui/issues/issue-29740.rs2
-rw-r--r--src/test/ui/issues/issue-29743.rs2
-rw-r--r--src/test/ui/issues/issue-31260.rs2
-rw-r--r--src/test/ui/issues/issue-3149.rs2
-rw-r--r--src/test/ui/issues/issue-31597.rs2
-rw-r--r--src/test/ui/issues/issue-32324.rs2
-rw-r--r--src/test/ui/issues/issue-33140-traitobject-crate.rs2
-rw-r--r--src/test/ui/issues/issue-33264.rs2
-rw-r--r--src/test/ui/issues/issue-33287.rs2
-rw-r--r--src/test/ui/issues/issue-33903.rs2
-rw-r--r--src/test/ui/issues/issue-34194.rs2
-rw-r--r--src/test/ui/issues/issue-3424.rs2
-rw-r--r--src/test/ui/issues/issue-34751.rs2
-rw-r--r--src/test/ui/issues/issue-34780.rs2
-rw-r--r--src/test/ui/issues/issue-35376.rs2
-rw-r--r--src/test/ui/issues/issue-35546.rs2
-rw-r--r--src/test/ui/issues/issue-3563-2.rs2
-rw-r--r--src/test/ui/issues/issue-36075.rs2
-rw-r--r--src/test/ui/issues/issue-3609.rs2
-rw-r--r--src/test/ui/issues/issue-36744-without-calls.rs2
-rw-r--r--src/test/ui/issues/issue-37323.rs2
-rw-r--r--src/test/ui/issues/issue-37598.rs2
-rw-r--r--src/test/ui/issues/issue-37655.rs2
-rw-r--r--src/test/ui/issues/issue-37725.rs2
-rw-r--r--src/test/ui/issues/issue-37733.rs2
-rw-r--r--src/test/ui/issues/issue-38727.rs2
-rw-r--r--src/test/ui/issues/issue-3874.rs2
-rw-r--r--src/test/ui/issues/issue-38875/issue-38875.rs2
-rw-r--r--src/test/ui/issues/issue-3888-2.rs2
-rw-r--r--src/test/ui/issues/issue-39089.rs2
-rw-r--r--src/test/ui/issues/issue-39467.rs2
-rw-r--r--src/test/ui/issues/issue-3979-2.rs2
-rw-r--r--src/test/ui/issues/issue-3991.rs2
-rw-r--r--src/test/ui/issues/issue-39984.rs2
-rw-r--r--src/test/ui/issues/issue-40136.rs2
-rw-r--r--src/test/ui/issues/issue-4025.rs2
-rw-r--r--src/test/ui/issues/issue-40510-2.rs2
-rw-r--r--src/test/ui/issues/issue-40510-4.rs2
-rw-r--r--src/test/ui/issues/issue-40962.rs2
-rw-r--r--src/test/ui/issues/issue-41272.rs2
-rw-r--r--src/test/ui/issues/issue-41298.rs2
-rw-r--r--src/test/ui/issues/issue-41628.rs2
-rw-r--r--src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs2
-rw-r--r--src/test/ui/issues/issue-41998.rs2
-rw-r--r--src/test/ui/issues/issue-42467.rs2
-rw-r--r--src/test/ui/issues/issue-42956.rs2
-rw-r--r--src/test/ui/issues/issue-43057.rs2
-rw-r--r--src/test/ui/issues/issue-43357.rs2
-rw-r--r--src/test/ui/issues/issue-43483.rs2
-rw-r--r--src/test/ui/issues/issue-44005.rs2
-rw-r--r--src/test/ui/issues/issue-44056.rs2
-rw-r--r--src/test/ui/issues/issue-44247.rs2
-rw-r--r--src/test/ui/issues/issue-44373-2.rs2
-rw-r--r--src/test/ui/issues/issue-44402.rs2
-rw-r--r--src/test/ui/issues/issue-4464.rs2
-rw-r--r--src/test/ui/issues/issue-44730.rs2
-rw-r--r--src/test/ui/issues/issue-44851.rs2
-rw-r--r--src/test/ui/issues/issue-45425.rs2
-rw-r--r--src/test/ui/issues/issue-46959.rs2
-rw-r--r--src/test/ui/issues/issue-46964.rs2
-rw-r--r--src/test/ui/issues/issue-47094.rs2
-rw-r--r--src/test/ui/issues/issue-47309.rs2
-rw-r--r--src/test/ui/issues/issue-47673.rs2
-rw-r--r--src/test/ui/issues/issue-47703-1.rs2
-rw-r--r--src/test/ui/issues/issue-47703-tuple.rs2
-rw-r--r--src/test/ui/issues/issue-47703.rs2
-rw-r--r--src/test/ui/issues/issue-47722.rs2
-rw-r--r--src/test/ui/issues/issue-47789.rs2
-rw-r--r--src/test/ui/issues/issue-4830.rs2
-rw-r--r--src/test/ui/issues/issue-48551.rs2
-rw-r--r--src/test/ui/issues/issue-49556.rs2
-rw-r--r--src/test/ui/issues/issue-49579.rs2
-rw-r--r--src/test/ui/issues/issue-49934.rs2
-rw-r--r--src/test/ui/issues/issue-50187.rs2
-rw-r--r--src/test/ui/issues/issue-50411.rs2
-rw-r--r--src/test/ui/issues/issue-50471.rs2
-rw-r--r--src/test/ui/issues/issue-50518.rs2
-rw-r--r--src/test/ui/issues/issue-50761.rs2
-rw-r--r--src/test/ui/issues/issue-50993.rs2
-rw-r--r--src/test/ui/issues/issue-51655.rs2
-rw-r--r--src/test/ui/issues/issue-51947.rs2
-rw-r--r--src/test/ui/issues/issue-52992.rs2
-rw-r--r--src/test/ui/issues/issue-53419.rs2
-rw-r--r--src/test/ui/issues/issue-5353.rs2
-rw-r--r--src/test/ui/issues/issue-53568.rs2
-rw-r--r--src/test/ui/issues/issue-53675-a-test-called-panic.rs2
-rw-r--r--src/test/ui/issues/issue-54387.rs2
-rw-r--r--src/test/ui/issues/issue-54521-1.rs2
-rw-r--r--src/test/ui/issues/issue-54943-1.rs2
-rw-r--r--src/test/ui/issues/issue-54943-2.rs2
-rw-r--r--src/test/ui/issues/issue-54943-3.rs2
-rw-r--r--src/test/ui/issues/issue-5500-1.rs2
-rw-r--r--src/test/ui/issues/issue-5572.rs2
-rw-r--r--src/test/ui/issues/issue-56128.rs2
-rw-r--r--src/test/ui/issues/issue-56202.rs2
-rw-r--r--src/test/ui/issues/issue-56411-aux.rs2
-rw-r--r--src/test/ui/issues/issue-57156.rs2
-rw-r--r--src/test/ui/issues/issue-57162.rs2
-rw-r--r--src/test/ui/issues/issue-57410-1.rs2
-rw-r--r--src/test/ui/issues/issue-57410.rs2
-rw-r--r--src/test/ui/issues/issue-5754.rs2
-rw-r--r--src/test/ui/issues/issue-5884.rs2
-rw-r--r--src/test/ui/issues/issue-5900.rs2
-rw-r--r--src/test/ui/issues/issue-5950.rs2
-rw-r--r--src/test/ui/issues/issue-60662.rs2
-rw-r--r--src/test/ui/issues/issue-60662.stdout2
-rw-r--r--src/test/ui/issues/issue-6341.rs2
-rw-r--r--src/test/ui/issues/issue-6470.rs2
-rw-r--r--src/test/ui/issues/issue-6557.rs2
-rw-r--r--src/test/ui/issues/issue-6898.rs2
-rw-r--r--src/test/ui/issues/issue-6991.rs2
-rw-r--r--src/test/ui/issues/issue-7268.rs2
-rw-r--r--src/test/ui/issues/issue-7607-2.rs2
-rw-r--r--src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs2
-rw-r--r--src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs2
-rw-r--r--src/test/ui/issues/issue-8398.rs2
-rw-r--r--src/test/ui/issues/issue-8521.rs2
-rw-r--r--src/test/ui/issues/issue-8578.rs2
-rw-r--r--src/test/ui/issues/issue-9110.rs2
-rw-r--r--src/test/ui/issues/issue-9243.rs2
-rw-r--r--src/test/ui/issues/issue-9249.rs2
-rw-r--r--src/test/ui/issues/issue-9719.rs2
-rw-r--r--src/test/ui/lint/command-line-lint-group-allow.rs2
-rw-r--r--src/test/ui/lint/command-line-lint-group-warn.rs2
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.fixed2
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.rs2
-rw-r--r--src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs2
-rw-r--r--src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs2
-rw-r--r--src/test/ui/lint/issue-54099-camel-case-underscore-types.rs2
-rw-r--r--src/test/ui/lint/issue-54538-unused-parens-lint.rs2
-rw-r--r--src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs2
-rw-r--r--src/test/ui/lint/lint-non-camel-case-variant.rs2
-rw-r--r--src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs2
-rw-r--r--src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs2
-rw-r--r--src/test/ui/lint/lint-nonstandard-style-unicode.rs2
-rw-r--r--src/test/ui/lint/lint-output-format-2.rs2
-rw-r--r--src/test/ui/lint/lint-stability-deprecated.rs2
-rw-r--r--src/test/ui/lint/lint-type-overflow2.rs16
-rw-r--r--src/test/ui/lint/lint-type-overflow2.stderr36
-rw-r--r--src/test/ui/lint/lint-unknown-feature-default.rs2
-rw-r--r--src/test/ui/lint/lint-unknown-feature.rs2
-rw-r--r--src/test/ui/lint/lints-in-foreign-macros.rs2
-rw-r--r--src/test/ui/lint/must-use-ops.rs2
-rw-r--r--src/test/ui/lint/must_use-array.rs47
-rw-r--r--src/test/ui/lint/must_use-array.stderr44
-rw-r--r--src/test/ui/lint/must_use-trait.rs17
-rw-r--r--src/test/ui/lint/must_use-trait.stderr28
-rw-r--r--src/test/ui/lint/not_found.rs2
-rw-r--r--src/test/ui/lint/reasons.rs2
-rw-r--r--src/test/ui/lint/type-overflow.rs2
-rw-r--r--src/test/ui/lint/unreachable_pub-pub_crate.rs2
-rw-r--r--src/test/ui/lint/unreachable_pub.rs2
-rw-r--r--src/test/ui/lint/unused_import_warning_issue_45268.rs2
-rw-r--r--src/test/ui/lint/unused_labels.rs2
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.rs2
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr12
-rw-r--r--src/test/ui/lint/use-redundant.rs2
-rw-r--r--src/test/ui/loops/loops-reject-duplicate-labels-2.rs2
-rw-r--r--src/test/ui/loops/loops-reject-duplicate-labels.rs2
-rw-r--r--src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs2
-rw-r--r--src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs2
-rw-r--r--src/test/ui/macros/macro-expanded-include/test.rs2
-rw-r--r--src/test/ui/macros/macro-path-prelude-pass.rs2
-rw-r--r--src/test/ui/macros/macro-shadowing-relaxed.rs2
-rw-r--r--src/test/ui/macros/macro-stmt-matchers.rs2
-rw-r--r--src/test/ui/macros/macro-tt-matchers.rs2
-rw-r--r--src/test/ui/macros/macro-use-scope.rs2
-rw-r--r--src/test/ui/macros/must-use-in-macro-55516.rs2
-rw-r--r--src/test/ui/macros/trace-macro.rs2
-rw-r--r--src/test/ui/malformed/malformed-regressions.rs2
-rw-r--r--src/test/ui/maybe-bounds-where-cpass.rs2
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-subst-index.rs2
-rw-r--r--src/test/ui/methods/method-trait-object-with-hrtb.rs2
-rw-r--r--src/test/ui/missing/missing-semicolon-warning.rs2
-rw-r--r--src/test/ui/never-assign-dead-code.rs2
-rw-r--r--src/test/ui/never_transmute_never.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs2
-rw-r--r--src/test/ui/nll/constant.rs2
-rw-r--r--src/test/ui/nll/drop-may-dangle.rs2
-rw-r--r--src/test/ui/nll/empty-type-predicate.rs2
-rw-r--r--src/test/ui/nll/extra-unused-mut.rs2
-rw-r--r--src/test/ui/nll/generator-distinct-lifetime.rs2
-rw-r--r--src/test/ui/nll/issue-16223.rs2
-rw-r--r--src/test/ui/nll/issue-21114-ebfull.rs2
-rw-r--r--src/test/ui/nll/issue-21114-kixunil.rs2
-rw-r--r--src/test/ui/nll/issue-22323-temp-destruction.rs2
-rw-r--r--src/test/ui/nll/issue-30104.rs2
-rw-r--r--src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs2
-rw-r--r--src/test/ui/nll/issue-43058.rs2
-rw-r--r--src/test/ui/nll/issue-47022.rs2
-rw-r--r--src/test/ui/nll/issue-50716-1.rs2
-rw-r--r--src/test/ui/nll/issue-51351.rs2
-rw-r--r--src/test/ui/nll/issue-52078.rs2
-rw-r--r--src/test/ui/nll/issue-53119.rs2
-rw-r--r--src/test/ui/nll/issue-53570.rs2
-rw-r--r--src/test/ui/nll/issue-55344.rs2
-rw-r--r--src/test/ui/nll/issue-55651.rs2
-rw-r--r--src/test/ui/nll/issue-57280-1.rs2
-rw-r--r--src/test/ui/nll/issue-57280.rs2
-rw-r--r--src/test/ui/nll/issue-61311-normalize.rs2
-rw-r--r--src/test/ui/nll/issue-61320-normalize.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-uninitialized.rs2
-rw-r--r--src/test/ui/nll/projection-return.rs2
-rw-r--r--src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs2
-rw-r--r--src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs2
-rw-r--r--src/test/ui/nll/relate_tys/issue-48071.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/issue-53789-1.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/issue-53789-2.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/issue-55756.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/projection-body.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/projection-where-clause-env.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs2
-rw-r--r--src/test/ui/nll/user-annotations/downcast-infer.rs2
-rw-r--r--src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs2
-rw-r--r--src/test/ui/no-warn-on-field-replace-issue-34101.rs2
-rw-r--r--src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs2
-rw-r--r--src/test/ui/object-safety/object-safety-by-value-self.rs2
-rw-r--r--src/test/ui/object-safety/object-safety-phantom-fn.rs2
-rw-r--r--src/test/ui/panic_implementation-closures.rs2
-rw-r--r--src/test/ui/parser/bounds-obj-parens.rs2
-rw-r--r--src/test/ui/parser/impl-qpath.rs2
-rw-r--r--src/test/ui/parser/macro-bad-delimiter-ident.rs2
-rw-r--r--src/test/ui/parser/macro-bad-delimiter-ident.stderr6
-rw-r--r--src/test/ui/parser/trailing-plus-in-bounds.rs2
-rw-r--r--src/test/ui/parser/trait-plusequal-splitting.rs2
-rw-r--r--src/test/ui/parser/underscore-suffix-for-string.rs2
-rw-r--r--src/test/ui/print-fuel/print-fuel.rs2
-rw-r--r--src/test/ui/print_type_sizes/anonymous.rs2
-rw-r--r--src/test/ui/print_type_sizes/generics.rs5
-rw-r--r--src/test/ui/print_type_sizes/multiple_types.rs2
-rw-r--r--src/test/ui/print_type_sizes/niche-filling.rs5
-rw-r--r--src/test/ui/print_type_sizes/no_duplicates.rs5
-rw-r--r--src/test/ui/print_type_sizes/packed.rs5
-rw-r--r--src/test/ui/print_type_sizes/padding.rs2
-rw-r--r--src/test/ui/print_type_sizes/repr-align.rs5
-rw-r--r--src/test/ui/print_type_sizes/repr_int_c.rs2
-rw-r--r--src/test/ui/print_type_sizes/uninhabited.rs5
-rw-r--r--src/test/ui/print_type_sizes/variants.rs2
-rw-r--r--src/test/ui/privacy/issue-57264-1.rs2
-rw-r--r--src/test/ui/privacy/issue-57264-2.rs2
-rw-r--r--src/test/ui/privacy/private-in-public-existential.rs2
-rw-r--r--src/test/ui/privacy/private-in-public-expr-pat.rs2
-rw-r--r--src/test/ui/privacy/restricted/lookup-ignores-private.rs2
-rw-r--r--src/test/ui/proc-macro/attributes-included.rs2
-rw-r--r--src/test/ui/proc-macro/auxiliary/generate-mod.rs1
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowed.rs2
-rw-r--r--src/test/ui/proc-macro/derive-in-mod.rs2
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.rs2
-rw-r--r--src/test/ui/proc-macro/edition-imports-2018.rs2
-rw-r--r--src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs2
-rw-r--r--src/test/ui/proc-macro/helper-attr-blocked-by-import.rs2
-rw-r--r--src/test/ui/proc-macro/issue-53481.rs2
-rw-r--r--src/test/ui/proc-macro/macro-use-attr.rs2
-rw-r--r--src/test/ui/proc-macro/macro-use-bang.rs2
-rw-r--r--src/test/ui/proc-macro/no-missing-docs.rs2
-rw-r--r--src/test/ui/range/range_traits-4.rs2
-rw-r--r--src/test/ui/range/range_traits-5.rs2
-rw-r--r--src/test/ui/range/range_traits-7.rs2
-rw-r--r--src/test/ui/reachable/expr_andand.rs2
-rw-r--r--src/test/ui/reachable/expr_oror.rs2
-rw-r--r--src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs2
-rw-r--r--src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs2
-rw-r--r--src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs2
-rw-r--r--src/test/ui/regions/region-object-lifetime-1.rs2
-rw-r--r--src/test/ui/regions/region-object-lifetime-3.rs2
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs2
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs2
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-projection-hrtype.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-projection-trait-def.rs2
-rw-r--r--src/test/ui/regions/regions-outlives-scalar.rs2
-rw-r--r--src/test/ui/removing-extern-crate.fixed2
-rw-r--r--src/test/ui/removing-extern-crate.rs2
-rw-r--r--src/test/ui/resolve/issue-57523.rs2
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs2
-rw-r--r--src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs2
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/issue-54467.rs2
-rw-r--r--src/test/ui/rfc-2166-underscore-imports/basic.rs2
-rw-r--r--src/test/ui/rfc-2166-underscore-imports/duplicate.rs2
-rw-r--r--src/test/ui/rfc-2166-underscore-imports/intercrate.rs2
-rw-r--r--src/test/ui/rfc-2306/convert-id-const-with-gate.rs2
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs2
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout2
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs2
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs2
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs2
-rw-r--r--src/test/ui/rfc1598-generic-associated-types/shadowing.rs2
-rw-r--r--src/test/ui/rmeta-lib-pass.rs2
-rw-r--r--src/test/ui/rmeta-pass.rs2
-rw-r--r--src/test/ui/rmeta-priv-warn.rs2
-rw-r--r--src/test/ui/rust-2018/edition-lint-paths-2018.rs2
-rw-r--r--src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs2
-rw-r--r--src/test/ui/rust-2018/macro-use-warned-against.rs2
-rw-r--r--src/test/ui/rust-2018/proc-macro-crate-in-paths.rs2
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.fixed2
-rw-r--r--src/test/ui/rust-2018/remove-extern-crate.rs2
-rw-r--r--src/test/ui/rust-2018/suggestions-not-always-applicable.fixed2
-rw-r--r--src/test/ui/rust-2018/suggestions-not-always-applicable.rs2
-rw-r--r--src/test/ui/rust-2018/try-ident.fixed2
-rw-r--r--src/test/ui/rust-2018/try-ident.rs2
-rw-r--r--src/test/ui/rust-2018/try-macro.fixed2
-rw-r--r--src/test/ui/rust-2018/try-macro.rs2
-rw-r--r--src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs2
-rw-r--r--src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs2
-rw-r--r--src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs2
-rw-r--r--src/test/ui/rust-2018/uniform-paths/prelude.rs2
-rw-r--r--src/test/ui/save-analysis/emit-notifications.rs5
-rw-r--r--src/test/ui/self/explicit-self-closures.rs2
-rw-r--r--src/test/ui/self/self-in-typedefs.rs2
-rw-r--r--src/test/ui/self/self-type-param.rs2
-rw-r--r--src/test/ui/single-use-lifetime/one-use-in-fn-return.rs2
-rw-r--r--src/test/ui/single-use-lifetime/one-use-in-struct.rs2
-rw-r--r--src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs2
-rw-r--r--src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs2
-rw-r--r--src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs2
-rw-r--r--src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs2
-rw-r--r--src/test/ui/span/issue-24690.rs2
-rw-r--r--src/test/ui/span/macro-span-replacement.rs2
-rw-r--r--src/test/ui/span/multispan-import-lint.rs2
-rw-r--r--src/test/ui/static/static-extern-type.rs2
-rw-r--r--src/test/ui/static_sized_requirement.rs2
-rw-r--r--src/test/ui/suggestions/issue-57672.rs2
-rw-r--r--src/test/ui/test-on-macro.rs2
-rw-r--r--src/test/ui/test-shadowing/test-cant-be-shadowed.rs2
-rw-r--r--src/test/ui/test-should-panic-attr.rs2
-rw-r--r--src/test/ui/traits/conservative_impl_trait.rs2
-rw-r--r--src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs2
-rw-r--r--src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs2
-rw-r--r--src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs2
-rw-r--r--src/test/ui/traits/trait-privacy.rs2
-rw-r--r--src/test/ui/traits/trait-with-dst.rs2
-rw-r--r--src/test/ui/traits/traits-issue-23003-overflow.rs2
-rw-r--r--src/test/ui/try-poll.rs2
-rw-r--r--src/test/ui/type-alias-enum-variants-panic.rs17
-rw-r--r--src/test/ui/type-alias-enum-variants-panic.stderr21
-rw-r--r--src/test/ui/type-alias-enum-variants-priority-2.rs13
-rw-r--r--src/test/ui/type-alias-enum-variants-priority-2.stderr12
-rw-r--r--src/test/ui/type-alias-enum-variants-priority-3.rs10
-rw-r--r--src/test/ui/type-alias-enum-variants-priority.rs19
-rw-r--r--src/test/ui/type-alias-enum-variants.rs11
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs (renamed from src/test/ui/pattern/enum-variant-generic-args.rs)22
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs (renamed from src/test/ui/enum-variant-generic-args.rs)36
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr (renamed from src/test/ui/enum-variant-generic-args.stderr)124
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs23
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr22
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs37
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr (renamed from src/test/ui/type-alias-enum-variants-priority.stderr)6
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs (renamed from src/test/ui/issues/issue-58006.rs)1
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr (renamed from src/test/ui/issues/issue-58006.stderr)2
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs21
-rw-r--r--src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr43
-rw-r--r--src/test/ui/type-alias-enum-variants/issue-57866.rs (renamed from src/test/ui/issues/issue-57866.rs)4
-rw-r--r--src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs4
-rw-r--r--src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs14
-rw-r--r--src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr (renamed from src/test/ui/type-alias-enum-variants.stderr)4
-rw-r--r--src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs11
-rw-r--r--src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr (renamed from src/test/ui/type-alias-enum-variants-priority-3.stderr)2
-rw-r--r--src/test/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs69
-rw-r--r--src/test/ui/type/type-alias-bounds.rs2
-rw-r--r--src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs2
-rw-r--r--src/test/ui/uninhabited/privately-uninhabited-dead-code.rs2
-rw-r--r--src/test/ui/union/union-const-eval.rs2
-rw-r--r--src/test/ui/unreachable/unreachable-try-pattern.rs2
-rw-r--r--src/test/ui/unrestricted-attribute-tokens.rs2
-rw-r--r--src/test/ui/unsized-locals/unsized-index.rs2
-rw-r--r--src/test/ui/user-defined-macro-rules.rs10
-rw-r--r--src/test/ui/user-defined-macro-rules.stderr8
-rw-r--r--src/test/ui/variance/variance-use-contravariant-struct-2.rs2
-rw-r--r--src/test/ui/variance/variance-use-covariant-struct-2.rs2
-rw-r--r--src/tools/compiletest/src/common.rs33
-rw-r--r--src/tools/compiletest/src/header.rs31
-rw-r--r--src/tools/compiletest/src/main.rs16
-rw-r--r--src/tools/compiletest/src/runtest.rs36
m---------src/tools/miri16
-rwxr-xr-xsrc/tools/publish_toolstate.py61
m---------src/tools/rls0
1131 files changed, 6690 insertions, 3701 deletions
diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml
index 8035feeeefb..2e6c3b7a992 100644
--- a/.azure-pipelines/auto.yml
+++ b/.azure-pipelines/auto.yml
@@ -138,9 +138,8 @@ jobs:
         IMAGE: x86_64-gnu-full-bootstrap
       x86_64-gnu-aux:
         IMAGE: x86_64-gnu-aux
-        # FIXME: needs reenabling here rather than Travis
-      # x86_64-gnu-tools:
-      #   IMAGE: x86_64-gnu-tools
+      x86_64-gnu-tools:
+        IMAGE: x86_64-gnu-tools
       x86_64-gnu-debug:
         IMAGE: x86_64-gnu-debug
       x86_64-gnu-nopt:
@@ -252,12 +251,10 @@ jobs:
         RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
         VCVARS_BAT: vcvars64.bat
       # MSVC tools tests
-      # FIXME: broken on azure right now, need to figure out a cause and
-      # reenable
-      # x86_64-msvc-tools:
-      #   MSYS_BITS: 64
-      #   SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
-      #   RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
+      x86_64-msvc-tools:
+        MSYS_BITS: 64
+        SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
+        RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
 
       # 32/64-bit MinGW builds.
       #
diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml
index 271f9d382ff..1ece3ceb088 100644
--- a/.azure-pipelines/steps/run.yml
+++ b/.azure-pipelines/steps/run.yml
@@ -8,6 +8,13 @@
 
 steps:
 
+# Disable automatic line ending conversion, which is enabled by default on
+# Azure's Windows image. Having the conversion enabled caused regressions both
+# in our test suite (it broke miri tests) and in the ecosystem, since we
+# started shipping install scripts with CRLF endings instead of the old LF.
+- bash: git config --global core.autocrlf false
+  displayName: "Disable git automatic line ending conversion"
+
 - checkout: self
   fetchDepth: 2
 
diff --git a/.mailmap b/.mailmap
index 5673cc5cfbc..c5ecfb54fca 100644
--- a/.mailmap
+++ b/.mailmap
@@ -167,6 +167,8 @@ Matthijs Hofstra <thiezz@gmail.com>
 Melody Horn <melody@boringcactus.com> <mathphreak@gmail.com>
 Michael Williams <m.t.williams@live.com>
 Michael Woerister <michaelwoerister@posteo> <michaelwoerister@gmail>
+Michael Woerister <michaelwoerister@posteo> <michaelwoerister@users.noreply.github.com>
+Michael Woerister <michaelwoerister@posteo> <michaelwoerister@posteo.net>
 Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com>
 Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
 Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
diff --git a/.travis.yml b/.travis.yml
index ec90dd3c8fb..1d35ea0efac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,164 +1,10 @@
 language: shell
-sudo: required
-dist: xenial
-services:
-  - docker
-addons:
-  apt:
-    packages:
-      - gdb
+script: echo Travis CI is not used anymore
 
-git:
-  depth: 2
-  submodules: false
-
-env:
-  global:
-    - CI_JOB_NAME=$TRAVIS_JOB_NAME
-
-matrix:
-  fast_finish: true
-  include:
-    - env: IMAGE=x86_64-gnu-tools
-      name: x86_64-gnu-tools
-      if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/)
-
-before_install:
-  # We'll use the AWS cli to download/upload cached docker layers as well as
-  # push our deployments, so download that here.
-  - pip install --user awscli; export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/
-  - mkdir -p $HOME/rustsrc
-  # FIXME(#46924): these two commands are required to enable IPv6,
-  # they shouldn't exist, please revert once more official solutions appeared.
-  # see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729
-  - if [ "$TRAVIS_OS_NAME" = linux ]; then
-      echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
-      sudo service docker restart;
-    fi
-
-install:
-  - case "$TRAVIS_OS_NAME" in
-        linux)
-          travis_retry curl -fo $HOME/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl &&
-            chmod +x $HOME/stamp &&
-            export PATH=$PATH:$HOME
-          ;;
-        osx)
-          if [[ "$SCRIPT" == "./x.py dist" ]]; then
-            travis_retry brew update &&
-            travis_retry brew install xz &&
-            travis_retry brew install swig@3 &&
-            brew link --force swig@3;
-          fi &&
-          travis_retry curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin &&
-            chmod +x /usr/local/bin/sccache &&
-          travis_retry curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
-            chmod +x /usr/local/bin/stamp &&
-          travis_retry curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - &&
-            export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang &&
-            export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ &&
-            export AR=ar
-          ;;
-    esac
-
-before_script:
-  - >
-      echo "#### Disk usage before running script:";
-      df -h;
-      du . | sort -nr | head -n100
-  - >
-      RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc";
-      if [ "$TRAVIS_OS_NAME" = "osx" ]; then
-          export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh";
-      else
-          export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE";
-          # Enable core dump on Linux.
-          sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern';
-      fi
-  - >
-      if [ "$IMAGE" = mingw-check ]; then
-        # verify the publish_toolstate script works.
-        git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git;
-        cd rust-toolstate;
-        python2.7 "$TRAVIS_BUILD_DIR/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "";
-        cd ..;
-        rm -rf rust-toolstate;
-      fi
-
-# Log time information from this machine and an external machine for insight into possible
-# clock drift. Timezones don't matter since relative deltas give all the necessary info.
-script:
-  - >
-      date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
-  - stamp sh -x -c "$RUN_SCRIPT"
-  - >
-      date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
-
-after_success:
-  - >
-      echo "#### Build successful; Disk usage after running script:";
-      df -h;
-      du . | sort -nr | head -n100
-  - >
-      if [ "$DEPLOY$DEPLOY_ALT" == "1" ]; then
-        mkdir -p deploy/$TRAVIS_COMMIT;
-        if [ "$TRAVIS_OS_NAME" == "osx" ]; then
-            rm -rf build/dist/doc &&
-            cp -r build/dist/* deploy/$TRAVIS_COMMIT;
-        else
-            rm -rf obj/build/dist/doc &&
-            cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
-        fi;
-        ls -la deploy/$TRAVIS_COMMIT;
-        deploy_dir=rustc-builds;
-        if [ "$DEPLOY_ALT" == "1" ]; then
-            deploy_dir=rustc-builds-alt;
-        fi;
-        travis_retry aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://rust-lang-ci2/$deploy_dir
-      fi
-
-after_failure:
-  - >
-      echo "#### Build failed; Disk usage after running script:";
-      df -h;
-      du . | sort -nr | head -n100
-
-  # Random attempt at debugging currently. Just poking around in here to see if
-  # anything shows up.
-
-  # Dump backtrace for macOS
-  - ls -lat $HOME/Library/Logs/DiagnosticReports/
-  - find $HOME/Library/Logs/DiagnosticReports
-      -type f
-      -name '*.crash'
-      -not -name '*.stage2-*.crash'
-      -not -name 'com.apple.CoreSimulator.CoreSimulatorService-*.crash'
-      -exec printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" {} \;
-      -exec head -750 {} \;
-      -exec echo travis_fold":"end:crashlog \; || true
-
-  # Dump backtrace for Linux
-  - ln -s . checkout &&
-    for CORE in obj/cores/core.*; do
-      EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|');
-      if [ -f "$EXE" ]; then
-        printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE";
-        gdb --batch -q -c "$CORE" "$EXE"
-          -iex 'set auto-load off'
-          -iex 'dir src/'
-          -iex 'set sysroot .'
-          -ex bt
-          -ex q;
-        echo travis_fold":"end:crashlog;
-      fi;
-    done || true
-
-  # see #50887
-  - cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
-
-  # attempt to debug anything killed by the oom killer on linux, just to see if
-  # it happened
-  - dmesg | grep -i kill
+branches:
+  only:
+    - auto
+    - try
 
 notifications:
   email: false
diff --git a/Cargo.lock b/Cargo.lock
index eaec52a7a15..98dd10955d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1030,7 +1030,7 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1760,11 +1760,8 @@ dependencies = [
 
 [[package]]
 name = "new_debug_unreachable"
-version = "1.0.1"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "nodrop"
@@ -3450,7 +3447,7 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4039,14 +4036,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "unreachable"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "unstable-book-gen"
 version = "0.1.0"
 dependencies = [
@@ -4125,11 +4114,6 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
 name = "vte"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4388,7 +4372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
 "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
-"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
+"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum num-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8af1847c907c2f04d7bfd572fb25bbb4385c637fe5be163cf2f8c5d778fe1e7d"
 "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
@@ -4552,7 +4536,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
-"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
 "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c"
@@ -4562,7 +4545,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 "checksum vergen 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6aba5e34f93dc7051dfad05b98a18e9156f27e7b431fe1d2398cb6061c0a1dba"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf"
 "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
diff --git a/RELEASES.md b/RELEASES.md
index b6e2171f6ee..5ceeea8d037 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -309,9 +309,9 @@ Misc
 
 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
+- [`Command::before_exec` is being replaced by the unsafe method
+  `Command::pre_exec`][58059] and will be deprecated with Rust 1.37.0.
+- [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/
diff --git a/appveyor.yml b/appveyor.yml
index ee1511a0394..003de85184c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,113 +1,8 @@
-environment:
-  # This is required for at least an AArch64 compiler in one image, and is also
-  # going to soon be required for compiling LLVM.
-  APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
-
-  # By default schannel checks revocation of certificates unlike some other SSL
-  # backends, but we've historically had problems on CI where a revocation
-  # server goes down presumably. See #43333 for more info
-  CARGO_HTTP_CHECK_REVOKE: false
-
-  matrix:
-  # MSVC tools tests
-  - CI_JOB_NAME: x86_64-msvc-tools
-    MSYS_BITS: 64
-    SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows
-    RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri
-
-matrix:
-  fast_finish: true
-
-clone_depth: 2
+clone_depth: 1
 build: false
 
-install:
-  # Print which AppVeyor agent version we're running on.
-  - appveyor version
-  # If we need to download a custom MinGW, do so here and set the path
-  # appropriately.
-  #
-  # Note that this *also* means that we're not using what is typically
-  # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where
-  # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we
-  # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe`
-  # file exists in there (which it doesn't by default).
-  - if defined MINGW_URL appveyor-retry appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE%
-  - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul
-  - if defined MINGW_URL set PATH=%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH%
-
-  # If we're compiling for MSVC then we, like most other distribution builders,
-  # switch to clang as the compiler. This'll allow us eventually to enable LTO
-  # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
-  # clang has an output mode compatible with MinGW that we need. If it does we
-  # should switch to clang for MinGW as well!
-  #
-  # Note that the LLVM installer is an NSIS installer
-  #
-  # Original downloaded here came from
-  # http://releases.llvm.org/8.0.0/LLVM-8.0.0-win64.exe
-  - if NOT defined MINGW_URL appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-8.0.0-win64.exe
-  - if NOT defined MINGW_URL .\LLVM-8.0.0-win64.exe /S /NCRC /D=C:\clang-rust
-  - if NOT defined MINGW_URL set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=C:\clang-rust\bin\clang-cl.exe
-
-  # Here we do a pretty heinous thing which is to mangle the MinGW installation
-  # we just had above. Currently, as of this writing, we're using MinGW-w64
-  # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to
-  # be the first version which contains a fix for #40546, builds randomly
-  # failing during LLVM due to ar.exe/ranlib.exe failures.
-  #
-  # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds
-  # to contain a regression in gdb (#40184). As a result if we were to use the
-  # gdb provided (7.11.1) then we would fail all debuginfo tests.
-  #
-  # In order to fix spurious failures (pretty high priority) we use 6.3.0. To
-  # avoid disabling gdb tests we download an *old* version of gdb, specifically
-  # that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb
-  # with the 6.2.0 gdb to get tests passing.
-  #
-  # Note that we don't literally overwrite the gdb.exe binary because it appears
-  # to just use gdborig.exe, so that's the binary we deal with instead.
-  - if defined MINGW_URL appveyor-retry appveyor DownloadFile %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe
-  - if defined MINGW_URL mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe
-
-  # Otherwise pull in the MinGW installed on appveyor
-  - if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH%
-
-  # Prefer the "native" Python as LLVM has trouble building with MSYS sometimes
-  - copy C:\Python27\python.exe C:\Python27\python2.7.exe
-  - set PATH=C:\Python27;%PATH%
-
-  # Download and install sccache
-  - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc
-  - mv 2018-04-26-sccache-x86_64-pc-windows-msvc sccache.exe
-  - set PATH=%PATH%;%CD%
-
-  # Download and install ninja
-  #
-  # Note that this is originally from the github releases patch of Ninja
-  - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip
-  - 7z x 2017-03-15-ninja-win.zip
-  - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
-  # - set PATH=%PATH%;%CD% -- this already happens above for sccache
-
-  # Install InnoSetup to get `iscc` used to produce installers
-  - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-08-22-is.exe
-  - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
-  - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
-
-  # Help debug some handle issues on AppVeyor
-  - appveyor-retry appveyor DownloadFile https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-05-15-Handle.zip
-  - mkdir handle
-  - 7z x -ohandle 2017-05-15-Handle.zip
-  - set PATH=%PATH%;%CD%\handle
-  - handle.exe -accepteula -help
-
 test_script:
-  - if not exist C:\cache\rustsrc\NUL mkdir C:\cache\rustsrc
-  - sh src/ci/init_repo.sh . /c/cache/rustsrc
-  - set SRC=.
-  - set NO_CCACHE=1
-  - sh src/ci/run.sh
+  - echo AppVeyor is not used anymore
 
 branches:
   only:
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 46c58d118f7..cab7443bf3f 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -598,6 +598,7 @@ fn test_with_no_doc_stage0() {
         bless: false,
         compare_mode: None,
         rustfix_coverage: false,
+        pass: None,
     };
 
     let build = Build::new(config);
@@ -640,6 +641,7 @@ fn test_exclude() {
         bless: false,
         compare_mode: None,
         rustfix_coverage: false,
+        pass: None,
     };
 
     let build = Build::new(config);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 4774c0a51c0..179accda0c8 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -58,6 +58,7 @@ pub enum Subcommand {
         /// Whether to automatically update stderr/stdout files
         bless: bool,
         compare_mode: Option<String>,
+        pass: Option<String>,
         test_args: Vec<String>,
         rustc_args: Vec<String>,
         fail_fast: bool,
@@ -199,6 +200,12 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
                     "mode describing what file the actual ui output will be compared to",
                     "COMPARE MODE",
                 );
+                opts.optopt(
+                    "",
+                    "pass",
+                    "force {check,build,run}-pass tests to this mode.",
+                    "check | build | run"
+                );
                 opts.optflag(
                     "",
                     "rustfix-coverage",
@@ -401,6 +408,7 @@ Arguments:
                 paths,
                 bless: matches.opt_present("bless"),
                 compare_mode: matches.opt_str("compare-mode"),
+                pass: matches.opt_str("pass"),
                 test_args: matches.opt_strs("test-args"),
                 rustc_args: matches.opt_strs("rustc-args"),
                 fail_fast: !matches.opt_present("no-fail-fast"),
@@ -524,6 +532,15 @@ impl Subcommand {
             _ => None,
         }
     }
+
+    pub fn pass(&self) -> Option<&str> {
+        match *self {
+            Subcommand::Test {
+                ref pass, ..
+            } => pass.as_ref().map(|s| &s[..]),
+            _ => None,
+        }
+    }
 }
 
 fn split(s: &[String]) -> Vec<String> {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 2f9bd067c31..1d54ca16a31 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1065,6 +1065,11 @@ impl Step for Compiletest {
             }
         });
 
+        if let Some(ref pass) = builder.config.cmd.pass() {
+            cmd.arg("--pass");
+            cmd.arg(pass);
+        }
+
         if let Some(ref nodejs) = builder.config.nodejs {
             cmd.arg("--nodejs").arg(nodejs);
         }
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index 116c16b2f35..c2cf77d56cb 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -22,7 +22,7 @@ shift
 
 export CFLAGS="-fPIC $CFLAGS"
 
-MUSL=musl-1.1.20
+MUSL=musl-1.1.22
 
 # may have been downloaded in a previous run
 if [ ! -d $MUSL ]; then
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 34708d1847f..3cda8d92797 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -13,5 +13,6 @@
 - [Targets](targets/index.md)
     - [Built-in Targets](targets/built-in.md)
     - [Custom Targets](targets/custom.md)
+- [Profile-guided Optimization](profile-guided-optimization.md)
 - [Linker-plugin based LTO](linker-plugin-lto.md)
 - [Contributing to `rustc`](contributing.md)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index a616409d9a4..3773a778302 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -214,3 +214,20 @@ This option lets you control what happens when the code panics.
 ## incremental
 
 This flag allows you to enable incremental compilation.
+
+## profile-generate
+
+This flag allows for creating instrumented binaries that will collect
+profiling data for use with profile-guided optimization (PGO). The flag takes
+an optional argument which is the path to a directory into which the
+instrumented binary will emit the collected data. See the chapter on
+[profile-guided optimization](profile-guided-optimization.html) for more
+information.
+
+## profile-use
+
+This flag specifies the profiling data file to be used for profile-guided
+optimization (PGO). The flag takes a mandatory argument which is the path
+to a valid `.profdata` file. See the chapter on
+[profile-guided optimization](profile-guided-optimization.html) for more
+information.
diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
new file mode 100644
index 00000000000..38be07a6440
--- /dev/null
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -0,0 +1,136 @@
+# Profile Guided Optimization
+
+`rustc` supports doing profile-guided optimization (PGO).
+This chapter describes what PGO is, what it is good for, and how it can be used.
+
+## What Is Profiled-Guided Optimization?
+
+The basic concept of PGO is to collect data about the typical execution of
+a program (e.g. which branches it is likely to take) and then use this data
+to inform optimizations such as inlining, machine-code layout,
+register allocation, etc.
+
+There are different ways of collecting data about a program's execution.
+One is to run the program inside a profiler (such as `perf`) and another
+is to create an instrumented binary, that is, a binary that has data
+collection built into it, and run that.
+The latter usually provides more accurate data and it is also what is
+supported by `rustc`.
+
+## Usage
+
+Generating a PGO-optimized program involves following a workflow with four steps:
+
+1. Compile the program with instrumentation enabled
+   (e.g. `rustc -Cprofile-generate=/tmp/pgo-data main.rs`)
+2. Run the instrumented program (e.g. `./main`) which generates a
+   `default_<id>.profraw` file
+3. Convert the `.profraw` file into a `.profdata` file using
+   LLVM's `llvm-profdata` tool
+4. Compile the program again, this time making use of the profiling data
+   (for example `rustc -Cprofile-use=merged.profdata main.rs`)
+
+An instrumented program will create one or more `.profraw` files, one for each
+instrumented binary. E.g. an instrumented executable that loads two instrumented
+dynamic libraries at runtime will generate three `.profraw` files. Running an
+instrumented binary multiple times, on the other hand, will re-use the
+respective `.profraw` files, updating them in place.
+
+These `.profraw` files have to be post-processed before they can be fed back
+into the compiler. This is done by the `llvm-profdata` tool. This tool
+is most easily installed via
+
+```bash
+rustup component add llvm-tools-preview
+```
+
+Note that installing the `llvm-tools-preview` component won't add
+`llvm-profdata` to the `PATH`. Rather, the tool can be found in:
+
+```bash
+~/.rustup/toolchains/<toolchain>/lib/rustlib/<target-triple>/bin/
+```
+
+Alternatively, an `llvm-profdata` coming with a recent LLVM or Clang
+version usually works too.
+
+The `llvm-profdata` tool merges multiple `.profraw` files into a single
+`.profdata` file that can then be fed back into the compiler via
+`-Cprofile-use`:
+
+```bash
+# STEP 1: Compile the binary with instrumentation
+rustc -Cprofile-generate=/tmp/pgo-data -O ./main.rs
+
+# STEP 2: Run the binary a few times, maybe with common sets of args.
+#         Each run will create or update `.profraw` files in /tmp/pgo-data
+./main mydata1.csv
+./main mydata2.csv
+./main mydata3.csv
+
+# STEP 3: Merge and post-process all the `.profraw` files in /tmp/pgo-data
+llvm-profdata merge -o ./merged.profdata /tmp/pgo-data
+
+# STEP 4: Use the merged `.profdata` file during optimization. All `rustc`
+#         flags have to be the same.
+rustc -Cprofile-use=./merged.profdata -O ./main.rs
+```
+
+### A Complete Cargo Workflow
+
+Using this feature with Cargo works very similar to using it with `rustc`
+directly. Again, we generate an instrumented binary, run it to produce data,
+merge the data, and feed it back into the compiler. Some things of note:
+
+- We use the `RUSTFLAGS` environment variable in order to pass the PGO compiler
+  flags to the compilation of all crates in the program.
+
+- We pass the `--target` flag to Cargo, which prevents the `RUSTFLAGS`
+  arguments to be passed to Cargo build scripts. We don't want the build
+  scripts to generate a bunch of `.profraw` files.
+
+- We pass `--release` to Cargo because that's where PGO makes the most sense.
+  In theory, PGO can also be done on debug builds but there is little reason
+  to do so.
+
+- It is recommended to use *absolute paths* for the argument of
+  `-Cprofile-generate` and `-Cprofile-use`. Cargo can invoke `rustc` with
+  varying working directories, meaning that `rustc` will not be able to find
+  the supplied `.profdata` file. With absolute paths this is not an issue.
+
+- It is good practice to make sure that there is no left-over profiling data
+  from previous compilation sessions. Just deleting the directory is a simple
+  way of doing so (see `STEP 0` below).
+
+This is what the entire workflow looks like:
+
+```bash
+# STEP 0: Make sure there is no left-over profiling data from previous runs
+rm -rf /tmp/pgo-data
+
+# STEP 1: Build the instrumented binaries
+RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" \
+    cargo build --release --target=x86_64-unknown-linux-gnu
+
+# STEP 2: Run the instrumented binaries with some typical data
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata1.csv
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata2.csv
+./target/x86_64-unknown-linux-gnu/release/myprogram mydata3.csv
+
+# STEP 3: Merge the `.profraw` files into a `.profdata` file
+llvm-profdata merge -o /tmp/pgo-data/merged.profdata /tmp/pgo-data
+
+# STEP 4: Use the `.profdata` file for guiding optimizations
+RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \
+    cargo build --release --target=x86_64-unknown-linux-gnu
+```
+
+## Further Reading
+
+`rustc`'s PGO support relies entirely on LLVM's implementation of the feature
+and is equivalent to what Clang offers via the `-fprofile-generate` /
+`-fprofile-use` flags. The [Profile Guided Optimization][clang-pgo] section
+in Clang's documentation is therefore an interesting read for anyone who wants
+to use PGO with Rust.
+
+[clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md
index a896ce819ae..c9acd3c307b 100644
--- a/src/doc/rustdoc/src/documentation-tests.md
+++ b/src/doc/rustdoc/src/documentation-tests.md
@@ -253,19 +253,6 @@ conversion, so type inference fails because the type is not unique. Please note
 that you must write the `(())` in one sequence without intermediate whitespace
 so that rustdoc understands you want an implicit `Result`-returning function.
 
-As of version 1.37.0, this simplification also works with `Option`s, which can
-be handy to test e.g. iterators or checked arithmetic, for example:
-
-```ignore
-/// ```
-/// let _ = &[].iter().next()?;
-///# Some(())
-/// ```
-```
-
-Note that the result must be a `Some(())` and this has to be written in one go.
-In this case disambiguating the result isn't required.
-
 ## Documenting macros
 
 Here’s an example of documenting a macro:
diff --git a/src/doc/unstable-book/src/language-features/member-constraints.md b/src/doc/unstable-book/src/language-features/member-constraints.md
new file mode 100644
index 00000000000..0d11c31aca6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/member-constraints.md
@@ -0,0 +1,29 @@
+# `member_constraints`
+
+The tracking issue for this feature is: [#61977]
+
+[#61977]: https://github.com/rust-lang/rust/issues/61977
+
+------------------------
+
+The `member_constraints` feature gate lets you use `impl Trait` syntax with
+multiple unrelated lifetime parameters.
+
+A simple example is:
+
+```rust
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T {}
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+  (x, y)
+}
+
+fn main() { }
+```
+
+Without the `member_constraints` feature gate, the above example is an
+error because both `'a` and `'b` appear in the impl Trait bounds, but
+neither outlives the other.
diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md
index 133174268ef..00c81f03ba1 100644
--- a/src/doc/unstable-book/src/language-features/slice-patterns.md
+++ b/src/doc/unstable-book/src/language-features/slice-patterns.md
@@ -1,8 +1,8 @@
 # `slice_patterns`
 
-The tracking issue for this feature is: [#23121]
+The tracking issue for this feature is: [#62254]
 
-[#23121]: https://github.com/rust-lang/rust/issues/23121
+[#62254]: https://github.com/rust-lang/rust/issues/62254
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md b/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md
deleted file mode 100644
index bcdeafc4b11..00000000000
--- a/src/doc/unstable-book/src/language-features/type-alias-enum-variants.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# `type_alias_enum_variants`
-
-The tracking issue for this feature is: [#49683]
-
-[#49683]: https://github.com/rust-lang/rust/issues/49683
-
-------------------------
-
-The `type_alias_enum_variants` feature enables the use of variants on type
-aliases that refer to enums, as both a constructor and a pattern. That is,
-it allows for the syntax `EnumAlias::Variant`, which behaves exactly the same
-as `Enum::Variant` (assuming that `EnumAlias` is an alias for some enum type
-`Enum`).
-
-Note that since `Self` exists as a type alias, this feature also enables the
-use of the syntax `Self::Variant` within an impl block for an enum type.
-
-```rust
-#![feature(type_alias_enum_variants)]
-
-enum Foo {
-    Bar(i32),
-    Baz { i: i32 },
-}
-
-type Alias = Foo;
-
-fn main() {
-    let t = Alias::Bar(0);
-    let t = Alias::Baz { i: 0 };
-    match t {
-        Alias::Bar(_i) => {}
-        Alias::Baz { i: _i } => {}
-    }
-}
-```
diff --git a/src/etc/cpu-usage-over-time-plot.sh b/src/etc/cpu-usage-over-time-plot.sh
index 724a21c3fc2..0905789079a 100755
--- a/src/etc/cpu-usage-over-time-plot.sh
+++ b/src/etc/cpu-usage-over-time-plot.sh
@@ -16,7 +16,7 @@
 
 set -ex
 
-bucket=rust-lang-ci-evalazure
+bucket=rust-lang-ci2
 commit=$1
 builder=$2
 
diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py
index c551346bb00..fe38c49d270 100644
--- a/src/etc/gdb_load_rust_pretty_printers.py
+++ b/src/etc/gdb_load_rust_pretty_printers.py
@@ -1,2 +1,3 @@
+import gdb
 import gdb_rust_pretty_printing
 gdb_rust_pretty_printing.register_printers(gdb.current_objfile())
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 9109a730cce..41966360377 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -367,12 +367,19 @@ impl<T: Clone> Clone for Box<T> {
     /// ```
     /// let x = Box::new(5);
     /// let y = x.clone();
+    ///
+    /// // The value is the same
+    /// assert_eq!(x, y);
+    ///
+    /// // But they are unique objects
+    /// assert_ne!(&*x as *const i32, &*y as *const i32);
     /// ```
     #[rustfmt::skip]
     #[inline]
     fn clone(&self) -> Box<T> {
         box { (**self).clone() }
     }
+
     /// Copies `source`'s contents into `self` without creating a new allocation.
     ///
     /// # Examples
@@ -380,10 +387,15 @@ impl<T: Clone> Clone for Box<T> {
     /// ```
     /// let x = Box::new(5);
     /// let mut y = Box::new(10);
+    /// let yp: *const i32 = &*y;
     ///
     /// y.clone_from(&x);
     ///
-    /// assert_eq!(*y, 5);
+    /// // The value is the same
+    /// assert_eq!(x, y);
+    ///
+    /// // And no allocation occurred
+    /// assert_eq!(yp, &*y);
     /// ```
     #[inline]
     fn clone_from(&mut self, source: &Box<T>) {
@@ -716,6 +728,14 @@ impl<I: Iterator + ?Sized> Iterator for Box<I> {
         (**self).nth(n)
     }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<I: Iterator + Sized> Iterator for Box<I> {
+    fn last(self) -> Option<I::Item> where I: Sized {
+        (*self).last()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
     fn next_back(&mut self) -> Option<I::Item> {
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index c898f064fd0..9f531f5b83c 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -1035,6 +1035,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
+
+    #[inline]
+    fn last(self) -> Option<&'a T> {
+        self.iter.last()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index 6b079fc87cc..ca35600e857 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -770,8 +770,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
         }
 
         // First, we merge `self` and `other` into a sorted sequence in linear time.
-        let self_iter = mem::replace(self, BTreeMap::new()).into_iter();
-        let other_iter = mem::replace(other, BTreeMap::new()).into_iter();
+        let self_iter = mem::take(self).into_iter();
+        let other_iter = mem::take(other).into_iter();
         let iter = MergeIter {
             left: self_iter.peekable(),
             right: other_iter.peekable(),
@@ -1193,6 +1193,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.length, Some(self.length))
     }
+
+    fn last(mut self) -> Option<(&'a K, &'a V)> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
@@ -1253,6 +1257,10 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.length, Some(self.length))
     }
+
+    fn last(mut self) -> Option<(&'a K, &'a mut V)> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1421,6 +1429,10 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    fn last(mut self) -> Option<&'a K> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1458,6 +1470,10 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    fn last(mut self) -> Option<&'a V> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1495,6 +1511,10 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
             unsafe { Some(self.next_unchecked()) }
         }
     }
+
+    fn last(mut self) -> Option<(&'a K, &'a V)> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1508,6 +1528,10 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    fn last(mut self) -> Option<&'a mut V> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1626,6 +1650,10 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
             unsafe { Some(self.next_unchecked()) }
         }
     }
+
+    fn last(mut self) -> Option<(&'a K, &'a mut V)> {
+        self.next_back()
+    }
 }
 
 impl<'a, K, V> RangeMut<'a, K, V> {
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index 16a96ca19b8..d3af910a82c 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -1019,6 +1019,9 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
+    fn last(mut self) -> Option<&'a T> {
+        self.next_back()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
@@ -1073,6 +1076,10 @@ impl<'a, T> Iterator for Range<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         self.iter.next().map(|(k, _)| k)
     }
+
+    fn last(mut self) -> Option<&'a T> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "btree_range", since = "1.17.0")]
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index 40a82d6feaa..db0d6e2f9b9 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -708,7 +708,7 @@ impl<T> LinkedList<T> {
         let len = self.len();
         assert!(at <= len, "Cannot split off at a nonexistent index");
         if at == 0 {
-            return mem::replace(self, Self::new());
+            return mem::take(self);
         } else if at == len {
             return Self::new();
         }
@@ -832,6 +832,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.len, Some(self.len))
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a T> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -881,6 +886,11 @@ impl<'a, T> Iterator for IterMut<'a, T> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         (self.len, Some(self.len))
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a mut T> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 71faf672962..573dd86b23a 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -2206,6 +2206,11 @@ impl<'a, T> Iterator for Iter<'a, T> {
         self.tail = self.head - iter.len();
         final_res
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a T> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2319,6 +2324,11 @@ impl<'a, T> Iterator for IterMut<'a, T> {
         accum = front.iter_mut().fold(accum, &mut f);
         back.iter_mut().fold(accum, &mut f)
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a mut T> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 5fc58c8ab5a..bfe7d12d9d0 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -112,6 +112,7 @@
 #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
+#![feature(mem_take)]
 
 // Allow testing this library
 
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 40104554fe5..70a93157c9e 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -203,7 +203,7 @@ impl ToOwned for str {
     }
 
     fn clone_into(&self, target: &mut String) {
-        let mut b = mem::replace(target, String::new()).into_bytes();
+        let mut b = mem::take(target).into_bytes();
         self.as_bytes().clone_into(&mut b);
         *target = unsafe { String::from_utf8_unchecked(b) }
     }
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 7f7722548f5..1b0d3c19692 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -2385,6 +2385,11 @@ impl Iterator for Drain<'_> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<char> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 5ddac673c9f..e0c724f557b 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -761,7 +761,6 @@ fn from_into_inner() {
     it.next().unwrap();
     let vec = it.collect::<Vec<_>>();
     assert_eq!(vec, [2, 3]);
-    #[cfg(not(miri))] // Miri does not support comparing dangling pointers
     assert!(ptr != vec.as_ptr());
 }
 
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 92fe0834dd0..c0544d7469c 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1367,6 +1367,40 @@ impl<T> Vec<T> {
             self.truncate(new_len);
         }
     }
+
+    /// Consumes and leaks the `Vec`, returning a mutable reference to the contents,
+    /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime
+    /// `'a`. If the type has only static references, or none at all, then this
+    /// may be chosen to be `'static`.
+    ///
+    /// This function is similar to the `leak` function on `Box`.
+    ///
+    /// This function is mainly useful for data that lives for the remainder of
+    /// the program's life. Dropping the returned reference will cause a memory
+    /// leak.
+    ///
+    /// # Examples
+    ///
+    /// Simple usage:
+    ///
+    /// ```
+    /// #![feature(vec_leak)]
+    ///
+    /// fn main() {
+    ///     let x = vec![1, 2, 3];
+    ///     let static_ref: &'static mut [usize] = Vec::leak(x);
+    ///     static_ref[0] += 1;
+    ///     assert_eq!(static_ref, &[2, 2, 3]);
+    /// }
+    /// ```
+    #[unstable(feature = "vec_leak", issue = "62195")]
+    #[inline]
+    pub fn leak<'a>(vec: Vec<T>) -> &'a mut [T]
+    where
+        T: 'a // Technically not needed, but kept to be explicit.
+    {
+        Box::leak(vec.into_boxed_slice())
+    }
 }
 
 impl<T: Clone> Vec<T> {
diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs
index c0ab364380f..e6a6fdde540 100644
--- a/src/libcore/ascii.rs
+++ b/src/libcore/ascii.rs
@@ -117,6 +117,7 @@ impl Iterator for EscapeDefault {
     type Item = u8;
     fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
+    fn last(mut self) -> Option<u8> { self.next_back() }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl DoubleEndedIterator for EscapeDefault {
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index 722c4c80516..e843303380a 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -337,16 +337,16 @@ impl char {
     /// ```
     /// // as chars
     /// let eastern = '東';
-    /// let capitol = '京';
+    /// let capital = '京';
     ///
     /// // both can be represented as three bytes
     /// assert_eq!(3, eastern.len_utf8());
-    /// assert_eq!(3, capitol.len_utf8());
+    /// assert_eq!(3, capital.len_utf8());
     ///
     /// // as a &str, these two are encoded in UTF-8
     /// let tokyo = "東京";
     ///
-    /// let len = eastern.len_utf8() + capitol.len_utf8();
+    /// let len = eastern.len_utf8() + capital.len_utf8();
     ///
     /// // we can see that they take six bytes total...
     /// assert_eq!(6, tokyo.len());
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index a697b7bd6e5..c0de8e2ceb3 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -251,12 +251,12 @@ pub trait AsMut<T: ?Sized> {
 ///
 /// # Examples
 ///
-/// [`String`] implements `Into<Vec<u8>>`:
+/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
 ///
 /// In order to express that we want a generic function to take all arguments that can be
 /// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
 /// For example: The function `is_hello` takes all arguments that can be converted into a
-/// `Vec<u8>`.
+/// [`Vec`]`<`[`u8`]`>`.
 ///
 /// ```
 /// fn is_hello<T: Into<Vec<u8>>>(s: T) {
@@ -274,6 +274,7 @@ pub trait AsMut<T: ?Sized> {
 /// [`String`]: ../../std/string/struct.String.html
 /// [`From`]: trait.From.html
 /// [`Into`]: trait.Into.html
+/// [`Vec`]: ../../std/vec/struct.Vec.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Into<T>: Sized {
     /// Performs the conversion.
@@ -410,12 +411,12 @@ pub trait TryInto<T>: Sized {
 ///
 /// This is useful when you are doing a type conversion that may
 /// trivially succeed but may also need special handling.
-/// For example, there is no way to convert an `i64` into an `i32`
-/// using the [`From`] trait, because an `i64` may contain a value
-/// that an `i32` cannot represent and so the conversion would lose data.
-/// This might be handled by truncating the `i64` to an `i32` (essentially
-/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning
-/// `i32::MAX`, or by some other method.  The `From` trait is intended
+/// For example, there is no way to convert an [`i64`] into an [`i32`]
+/// using the [`From`] trait, because an [`i64`] may contain a value
+/// that an [`i32`] cannot represent and so the conversion would lose data.
+/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
+/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
+/// [`i32::MAX`], or by some other method.  The [`From`] trait is intended
 /// for perfect conversions, so the `TryFrom` trait informs the
 /// programmer when a type conversion could go bad and lets them
 /// decide how to handle it.
@@ -425,8 +426,8 @@ pub trait TryInto<T>: Sized {
 /// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
 /// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
 /// is implemented and cannot fail -- the associated `Error` type for
-/// calling `T::try_from()` on a value of type `T` is `Infallible`.
-/// When the `!` type is stablized `Infallible` and `!` will be
+/// calling `T::try_from()` on a value of type `T` is [`Infallible`].
+/// When the [`!`] type is stablized [`Infallible`] and [`!`] will be
 /// equivalent.
 ///
 /// `TryFrom<T>` can be implemented as follows:
@@ -451,7 +452,7 @@ pub trait TryInto<T>: Sized {
 ///
 /// # Examples
 ///
-/// As described, [`i32`] implements `TryFrom<i64>`:
+/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
 ///
 /// ```
 /// use std::convert::TryFrom;
@@ -474,6 +475,8 @@ pub trait TryInto<T>: Sized {
 ///
 /// [`try_from`]: trait.TryFrom.html#tymethod.try_from
 /// [`TryInto`]: trait.TryInto.html
+/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
+/// [`!`]: ../../std/primitive.never.html
 #[stable(feature = "try_from", since = "1.34.0")]
 pub trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index cd61ab5c552..1865160bc3c 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -196,7 +196,7 @@ pub trait FromIterator<A>: Sized {
 /// ```rust
 /// fn collect_as_strings<T>(collection: T) -> Vec<String>
 ///     where T: IntoIterator,
-///           T::Item : std::fmt::Debug,
+///           T::Item: std::fmt::Debug,
 /// {
 ///     collection
 ///         .into_iter()
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 04c50329de3..d2d08a075b9 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -126,6 +126,7 @@
 #![feature(adx_target_feature)]
 #![feature(maybe_uninit_slice, maybe_uninit_array)]
 #![feature(external_doc)]
+#![feature(mem_take)]
 
 #[prelude_import]
 #[allow(unused)]
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index 3f4ff7c2f43..d9757d78dce 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -73,9 +73,9 @@ impl<T: ?Sized> !Send for *mut T { }
 /// impl Foo for Impl { }
 /// impl Bar for Impl { }
 ///
-/// let x: &Foo = &Impl;    // OK
-/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot
-///                         // be made into an object
+/// let x: &dyn Foo = &Impl;    // OK
+/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
+///                             // be made into an object
 /// ```
 ///
 /// [trait object]: ../../book/ch17-02-trait-objects.html
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 770d1ca8e75..b31522db474 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -510,6 +510,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// A simple example:
 ///
 /// ```
+/// #![feature(mem_take)]
+///
 /// use std::mem;
 ///
 /// let mut v: Vec<i32> = vec![1, 2];
@@ -540,7 +542,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// `self`, allowing it to be returned:
 ///
 /// ```
-/// # #![allow(dead_code)]
+/// #![feature(mem_take)]
+///
 /// use std::mem;
 ///
 /// # struct Buffer<T> { buf: Vec<T> }
@@ -549,6 +552,12 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 ///         mem::take(&mut self.buf)
 ///     }
 /// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf.len(), 2);
+///
+/// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
+/// assert_eq!(buffer.buf.len(), 0);
 /// ```
 ///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
@@ -583,17 +592,17 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 /// struct Buffer<T> { buf: Vec<T> }
 ///
 /// impl<T> Buffer<T> {
-///     fn get_and_reset(&mut self) -> Vec<T> {
+///     fn replace_index(&mut self, i: usize, v: T) -> T {
 ///         // error: cannot move out of dereference of `&mut`-pointer
-///         let buf = self.buf;
-///         self.buf = Vec::new();
-///         buf
+///         let t = self.buf[i];
+///         self.buf[i] = v;
+///         t
 ///     }
 /// }
 /// ```
 ///
-/// Note that `T` does not necessarily implement [`Clone`], so it can't even clone and reset
-/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
+/// Note that `T` does not necessarily implement [`Clone`], so we can't even clone `self.buf[i]` to
+/// avoid the move. But `replace` can be used to disassociate the original value at that index from
 /// `self`, allowing it to be returned:
 ///
 /// ```
@@ -602,10 +611,16 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 ///
 /// # struct Buffer<T> { buf: Vec<T> }
 /// impl<T> Buffer<T> {
-///     fn get_and_reset(&mut self) -> Vec<T> {
-///         mem::replace(&mut self.buf, Vec::new())
+///     fn replace_index(&mut self, i: usize, v: T) -> T {
+///         mem::replace(&mut self.buf[i], v)
 ///     }
 /// }
+///
+/// let mut buffer = Buffer { buf: vec![0, 1] };
+/// assert_eq!(buffer.buf[0], 0);
+///
+/// assert_eq!(buffer.replace_index(0, 2), 0);
+/// assert_eq!(buffer.buf[0], 2);
 /// ```
 ///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index eec4b149ddc..b27fd4098e1 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -777,15 +777,7 @@ impl<T> Option<T> {
     #[inline]
     #[stable(feature = "option_entry", since = "1.20.0")]
     pub fn get_or_insert(&mut self, v: T) -> &mut T {
-        match *self {
-            None => *self = Some(v),
-            _ => (),
-        }
-
-        match *self {
-            Some(ref mut v) => v,
-            None => unsafe { hint::unreachable_unchecked() },
-        }
+        self.get_or_insert_with(|| v)
     }
 
     /// Inserts a value computed from `f` into the option if it is [`None`], then
@@ -845,7 +837,7 @@ impl<T> Option<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn take(&mut self) -> Option<T> {
-        mem::replace(self, None)
+        mem::take(self)
     }
 
     /// Replaces the actual value in the option by the value given in parameter,
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index fccb00d768c..da781d7e9fe 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -100,7 +100,11 @@ pub use unique::Unique;
 ///   as the compiler doesn't need to prove that it's sound to elide the
 ///   copy.
 ///
+/// Unaligned values cannot be dropped in place, they must be copied to an aligned
+/// location first using [`ptr::read_unaligned`].
+///
 /// [`ptr::read`]: ../ptr/fn.read.html
+/// [`ptr::read_unaligned`]: ../ptr/fn.read_unaligned.html
 ///
 /// # Safety
 ///
@@ -108,8 +112,7 @@ pub use unique::Unique;
 ///
 /// * `to_drop` must be [valid] for reads.
 ///
-/// * `to_drop` must be properly aligned. See the example below for how to drop
-///   an unaligned pointer.
+/// * `to_drop` must be properly aligned.
 ///
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
@@ -153,31 +156,6 @@ pub use unique::Unique;
 /// assert!(weak.upgrade().is_none());
 /// ```
 ///
-/// Unaligned values cannot be dropped in place, they must be copied to an aligned
-/// location first:
-/// ```
-/// use std::ptr;
-/// use std::mem::{self, MaybeUninit};
-///
-/// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
-///     let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
-///     ptr::copy(to_drop, copy.as_mut_ptr(), 1);
-///     drop(copy.assume_init());
-/// }
-///
-/// #[repr(packed, C)]
-/// struct Packed {
-///     _padding: u8,
-///     unaligned: Vec<i32>,
-/// }
-///
-/// let mut p = Packed { _padding: 0, unaligned: vec![42] };
-/// unsafe {
-///     drop_after_copy(&mut p.unaligned as *mut _);
-///     mem::forget(p);
-/// }
-/// ```
-///
 /// Notice that the compiler performs this copy automatically when dropping packed structs,
 /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
 /// manually.
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index 155429b0e4f..75c329a7d6c 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -53,7 +53,7 @@
 /// let value: i32 = 123;
 ///
 /// // let the compiler make a trait object
-/// let object: &Foo = &value;
+/// let object: &dyn Foo = &value;
 ///
 /// // look at the raw representation
 /// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
@@ -65,7 +65,7 @@
 ///
 /// // construct a new object, pointing to a different `i32`, being
 /// // careful to use the `i32` vtable from `object`
-/// let synthesized: &Foo = unsafe {
+/// let synthesized: &dyn Foo = unsafe {
 ///      mem::transmute(raw::TraitObject {
 ///          data: &other_value as *const _ as *mut (),
 ///          vtable: raw_object.vtable,
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index c6d44324ef5..fe48e2458cd 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -4453,6 +4453,21 @@ impl<'a, T> DoubleEndedIterator for ChunksExact<'a, T> {
             Some(snd)
         }
     }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let len = self.len();
+        if n >= len {
+            self.v = &[];
+            None
+        } else {
+            let start = (len - 1 - n) * self.chunk_size;
+            let end = start + self.chunk_size;
+            let nth_back = &self.v[start..end];
+            self.v = &self.v[..start];
+            Some(nth_back)
+        }
+    }
 }
 
 #[stable(feature = "chunks_exact", since = "1.31.0")]
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 34f2d8917ea..b027e6bc051 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1333,6 +1333,11 @@ impl<'a> Iterator for Lines<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.0.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -3716,10 +3721,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
+    /// A string is a sequence of bytes. `start` in this context means the first
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be left side, and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the right side.
     ///
     /// # Examples
     ///
@@ -3755,10 +3760,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
+    /// A string is a sequence of bytes. `end` in this context means the last
+    /// position of that byte string; for a left-to-right language like English or
+    /// Russian, this will be right side, and for right-to-left languages like
+    /// like Arabic or Hebrew, this will be the left side.
     ///
     /// # Examples
     ///
@@ -3804,10 +3809,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. `start` in this context means the first
-    /// position of that byte string; for a left-to-right language like English or
-    /// Russian, this will be left side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the right side.
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
     ///
     /// # Examples
     ///
@@ -3840,10 +3845,10 @@ impl str {
     ///
     /// # Text directionality
     ///
-    /// A string is a sequence of bytes. `end` in this context means the last
-    /// position of that byte string; for a left-to-right language like English or
-    /// Russian, this will be right side, and for right-to-left languages like
-    /// like Arabic or Hebrew, this will be the left side.
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
     ///
     /// # Examples
     ///
@@ -4241,6 +4246,11 @@ impl<'a> Iterator for SplitWhitespace<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "split_whitespace", since = "1.1.0")]
@@ -4267,6 +4277,11 @@ impl<'a> Iterator for SplitAsciiWhitespace<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.inner.size_hint()
     }
+
+    #[inline]
+    fn last(mut self) -> Option<&'a str> {
+        self.next_back()
+    }
 }
 
 #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
diff --git a/src/libcore/tests/ascii.rs b/src/libcore/tests/ascii.rs
index ec98e0464c9..439ed0c81c8 100644
--- a/src/libcore/tests/ascii.rs
+++ b/src/libcore/tests/ascii.rs
@@ -151,7 +151,7 @@ macro_rules! assert_none {
                            stringify!($what), b);
                 }
             }
-        )*
+        )+
     }};
     ($what:ident, $($str:tt),+,) => (assert_none!($what,$($str),+))
 }
diff --git a/src/libcore/tests/fmt/mod.rs b/src/libcore/tests/fmt/mod.rs
index df1deeaeb97..d86e21cf40b 100644
--- a/src/libcore/tests/fmt/mod.rs
+++ b/src/libcore/tests/fmt/mod.rs
@@ -3,7 +3,6 @@ mod float;
 mod num;
 
 #[test]
-#[cfg(not(miri))] // Miri cannot print pointers
 fn test_format_flags() {
     // No residual flags left by pointer formatting
     let p = "".as_ptr();
@@ -13,7 +12,6 @@ fn test_format_flags() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot print pointers
 fn test_pointer_formats_data_pointer() {
     let b: &[u8] = b"";
     let s: &str = "";
diff --git a/src/libcore/tests/pattern.rs b/src/libcore/tests/pattern.rs
index b78ed021077..06c3a78c169 100644
--- a/src/libcore/tests/pattern.rs
+++ b/src/libcore/tests/pattern.rs
@@ -5,7 +5,7 @@ use std::str::pattern::*;
 macro_rules! search_asserts {
     ($haystack:expr, $needle:expr, $testname:expr, [$($func:ident),*], $result:expr) => {
         let mut searcher = $needle.into_searcher($haystack);
-        let arr = [$( Step::from(searcher.$func()) ),+];
+        let arr = [$( Step::from(searcher.$func()) ),*];
         assert_eq!(&arr[..], &$result, $testname);
     }
 }
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index 03fe1fe5a7c..569b3197d09 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -253,7 +253,6 @@ fn test_unsized_nonnull() {
 
 #[test]
 #[allow(warnings)]
-#[cfg(not(miri))] // Miri cannot hash pointers
 // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
 // ABI, or even point to an actual executable code, because the function itself is never invoked.
 #[no_mangle]
@@ -293,7 +292,7 @@ fn write_unaligned_drop() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_zst() {
     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
     // all, because no amount of elements will align the pointer.
@@ -308,7 +307,7 @@ fn align_offset_zst() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn align_offset_stride1() {
     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
     // number of bytes.
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 03e65d2fe0b..42ec9d451f7 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -276,6 +276,25 @@ fn test_chunks_exact_nth() {
 }
 
 #[test]
+fn test_chunks_exact_nth_back() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.chunks_exact(2);
+    assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
+    assert_eq!(c.next().unwrap(), &[0, 1]);
+    assert_eq!(c.next(), None);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.chunks_exact(3);
+    assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]);
+    assert_eq!(c2.next(), None);
+    assert_eq!(c2.next_back(), None);
+
+    let v3: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c3 = v3.chunks_exact(10);
+    assert_eq!(c3.nth_back(0), None);
+}
+
+#[test]
 fn test_chunks_exact_last() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
     let c = v.chunks_exact(2);
@@ -1396,7 +1415,7 @@ pub mod memchr {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_simple() {
     let bytes = [1u8, 2, 3, 4, 5, 6, 7];
     let (prefix, aligned, suffix) = unsafe { bytes.align_to::<u16>() };
@@ -1420,7 +1439,7 @@ fn test_align_to_zst() {
 }
 
 #[test]
-#[cfg(not(miri))] // Miri cannot compute actual alignment of an allocation
+#[cfg(not(miri))] // Miri does not compute a maximal `mid` for `align_offset`
 fn test_align_to_non_trivial() {
     #[repr(align(8))] struct U64(u64, u64);
     #[repr(align(8))] struct U64U64U32(u64, u64, u32);
diff --git a/src/libproc_macro/bridge/buffer.rs b/src/libproc_macro/bridge/buffer.rs
index 0d8cc552d61..a51e3a9a33d 100644
--- a/src/libproc_macro/bridge/buffer.rs
+++ b/src/libproc_macro/bridge/buffer.rs
@@ -78,7 +78,7 @@ impl<T: Copy> Buffer<T> {
     }
 
     pub(super) fn take(&mut self) -> Self {
-        mem::replace(self, Self::default())
+        mem::take(self)
     }
 
     pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
diff --git a/src/libproc_macro/bridge/scoped_cell.rs b/src/libproc_macro/bridge/scoped_cell.rs
index 6f7965095b6..89fb7070015 100644
--- a/src/libproc_macro/bridge/scoped_cell.rs
+++ b/src/libproc_macro/bridge/scoped_cell.rs
@@ -74,7 +74,7 @@ impl<T: LambdaL> ScopedCell<T> {
     }
 
     /// Sets the value in `self` to `value` while running `f`.
-    pub fn set<'a, R>(&self, value: <T as ApplyL<'a>>::Out, f: impl FnOnce() -> R) -> R {
+    pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R {
         self.replace(value, |_| f())
     }
 }
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 1e0f1ed578a..2c097238b95 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -25,6 +25,7 @@
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
 #![feature(optin_builtin_traits)]
+#![feature(mem_take)]
 #![feature(non_exhaustive)]
 #![feature(specialization)]
 
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index a7750edbb6f..a132575b0c6 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -1,11 +1,11 @@
 use crate::cfg::*;
 use crate::middle::region;
 use rustc_data_structures::graph::implementation as graph;
-use syntax::ptr::P;
 use crate::ty::{self, TyCtxt};
 
 use crate::hir::{self, PatKind};
 use crate::hir::def_id::DefId;
+use crate::hir::ptr::P;
 
 struct CFGBuilder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
@@ -30,7 +30,7 @@ struct LoopScope {
     break_index: CFGIndex,    // where to go on a `break`
 }
 
-pub fn construct<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body) -> CFG {
+pub fn construct(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
     let mut graph = graph::Graph::new();
     let entry = graph.add_node(CFGNodeData::Entry);
 
diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs
index db168d99a08..88fc7fbfad5 100644
--- a/src/librustc/cfg/mod.rs
+++ b/src/librustc/cfg/mod.rs
@@ -49,7 +49,7 @@ pub type CFGNode = graph::Node<CFGNodeData>;
 pub type CFGEdge = graph::Edge<CFGEdgeData>;
 
 impl CFG {
-    pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body) -> CFG {
+    pub fn new(tcx: TyCtxt<'_>, body: &hir::Body) -> CFG {
         construct::construct(tcx, body)
     }
 
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 82b0e50b50c..3d5e7dd0af1 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -142,9 +142,6 @@ macro_rules! define_dep_nodes {
                 }
             }
 
-            // FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties
-            // of queries
-            #[inline(always)]
             pub fn is_anon(&self) -> bool {
                 match *self {
                     $(
@@ -163,7 +160,6 @@ macro_rules! define_dep_nodes {
             }
 
             #[allow(unreachable_code)]
-            #[inline(always)]
             pub fn has_params(&self) -> bool {
                 match *self {
                     $(
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index c2e3c12cea8..b8c6c1e3723 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -841,32 +841,21 @@ impl DepGraph {
     //
     // This method will only load queries that will end up in the disk cache.
     // Other queries will not be executed.
-    pub fn exec_cache_promotions<'tcx>(&self, tcx: TyCtxt<'tcx>) {
-        let green_nodes: Vec<DepNode> = {
-            let data = self.data.as_ref().unwrap();
-            data.colors.values.indices().filter_map(|prev_index| {
-                match data.colors.get(prev_index) {
-                    Some(DepNodeColor::Green(_)) => {
-                        let dep_node = data.previous.index_to_node(prev_index);
-                        if dep_node.cache_on_disk(tcx) {
-                            Some(dep_node)
-                        } else {
-                            None
-                        }
-                    }
-                    None |
-                    Some(DepNodeColor::Red) => {
-                        // We can skip red nodes because a node can only be marked
-                        // as red if the query result was recomputed and thus is
-                        // already in memory.
-                        None
-                    }
+    pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) {
+        let data = self.data.as_ref().unwrap();
+        for prev_index in data.colors.values.indices() {
+            match data.colors.get(prev_index) {
+                Some(DepNodeColor::Green(_)) => {
+                    let dep_node = data.previous.index_to_node(prev_index);
+                    dep_node.try_load_from_on_disk_cache(tcx);
                 }
-            }).collect()
-        };
-
-        for dep_node in green_nodes {
-            dep_node.load_from_on_disk_cache(tcx);
+                None |
+                Some(DepNodeColor::Red) => {
+                    // We can skip red nodes because a node can only be marked
+                    // as red if the query result was recomputed and thus is
+                    // already in memory.
+                }
+            }
         }
     }
 
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index 4b84d56858c..9160b8024ee 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -347,7 +347,7 @@ fn is_c_like_enum(item: &hir::Item) -> bool {
     }
 }
 
-fn check_mod_attrs<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
         &mut CheckAttrVisitor { tcx }.as_deep_visitor()
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 9c4a208f0f9..ef05b57fb8f 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -39,6 +39,7 @@ use crate::hir::map::{DefKey, DefPathData, Definitions};
 use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
 use crate::hir::def::{Res, DefKind, PartialRes, PerNS};
 use crate::hir::{GenericArg, ConstArg};
+use crate::hir::ptr::P;
 use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                     ELIDED_LIFETIMES_IN_PATHS};
 use crate::middle::cstore::CrateStore;
@@ -61,7 +62,6 @@ use syntax::ast::*;
 use syntax::errors;
 use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::print::pprust;
-use syntax::ptr::P;
 use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned};
 use syntax::source_map::CompilerDesugaringKind::IfTemporary;
 use syntax::std_inject;
@@ -1111,7 +1111,7 @@ impl<'a> LoweringContext<'a> {
             },
         );
 
-        lowered_generics.params = lowered_generics
+        let mut lowered_params: Vec<_> = lowered_generics
             .params
             .into_iter()
             .chain(in_band_defs)
@@ -1121,7 +1121,7 @@ impl<'a> LoweringContext<'a> {
         // unsorted generic parameters at the moment, so we make sure
         // that they're ordered correctly here for now. (When we chain
         // the `in_band_defs`, we might make the order unsorted.)
-        lowered_generics.params.sort_by_key(|param| {
+        lowered_params.sort_by_key(|param| {
             match param.kind {
                 hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
                 hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
@@ -1129,6 +1129,8 @@ impl<'a> LoweringContext<'a> {
             }
         });
 
+        lowered_generics.params = lowered_params.into();
+
         (lowered_generics, res)
     }
 
@@ -1155,13 +1157,13 @@ impl<'a> LoweringContext<'a> {
         &mut self,
         capture_clause: CaptureBy,
         closure_node_id: NodeId,
-        ret_ty: Option<&Ty>,
+        ret_ty: Option<syntax::ptr::P<Ty>>,
         span: Span,
         body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
     ) -> hir::ExprKind {
         let capture_clause = self.lower_capture_clause(capture_clause);
         let output = match ret_ty {
-            Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
+            Some(ty) => FunctionRetTy::Ty(ty),
             None => FunctionRetTy::Default(span),
         };
         let ast_decl = FnDecl {
@@ -1278,8 +1280,8 @@ impl<'a> LoweringContext<'a> {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
-        let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
-        let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
+        let catch_scopes = mem::take(&mut self.catch_scopes);
+        let loop_scopes = mem::take(&mut self.loop_scopes);
         let ret = f(self);
         self.catch_scopes = catch_scopes;
         self.loop_scopes = loop_scopes;
@@ -2725,7 +2727,7 @@ impl<'a> LoweringContext<'a> {
 
         // ::std::future::Future<future_params>
         let future_path =
-            self.std_path(span, &[sym::future, sym::Future], Some(future_params), false);
+            P(self.std_path(span, &[sym::future, sym::Future], Some(future_params), false));
 
         hir::GenericBound::Trait(
             hir::PolyTraitRef {
@@ -3094,7 +3096,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_trait_ref(&mut self, p: &TraitRef, itctx: ImplTraitContext<'_>) -> hir::TraitRef {
         let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
-            hir::QPath::Resolved(None, path) => path.and_then(|path| path),
+            hir::QPath::Resolved(None, path) => path,
             qpath => bug!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
         };
         hir::TraitRef {
@@ -3620,7 +3622,7 @@ impl<'a> LoweringContext<'a> {
                             hir::Item {
                                 hir_id: new_id,
                                 ident,
-                                attrs: attrs.clone(),
+                                attrs: attrs.into_iter().cloned().collect(),
                                 node: item,
                                 vis,
                                 span,
@@ -3705,7 +3707,7 @@ impl<'a> LoweringContext<'a> {
                             hir::Item {
                                 hir_id: new_hir_id,
                                 ident,
-                                attrs: attrs.clone(),
+                                attrs: attrs.into_iter().cloned().collect(),
                                 node: item,
                                 vis,
                                 span: use_tree.span,
@@ -4567,7 +4569,7 @@ impl<'a> LoweringContext<'a> {
                         // `|x: u8| future_from_generator(|| -> X { ... })`.
                         let body_id = this.lower_fn_body(&outer_decl, |this| {
                             let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
-                                Some(&**ty)
+                                Some(ty.clone())
                             } else { None };
                             let async_body = this.make_async_expr(
                                 capture_clause, closure_id, async_ret_ty, body.span,
@@ -5577,7 +5579,7 @@ impl<'a> LoweringContext<'a> {
                         let principal = hir::PolyTraitRef {
                             bound_generic_params: hir::HirVec::new(),
                             trait_ref: hir::TraitRef {
-                                path: path.and_then(|path| path),
+                                path,
                                 hir_ref_id: hir_id,
                             },
                             span,
diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs
index 60465c04ec6..891a1956bc9 100644
--- a/src/librustc/hir/map/hir_id_validator.rs
+++ b/src/librustc/hir/map/hir_id_validator.rs
@@ -4,7 +4,7 @@ use crate::hir::itemlikevisit::ItemLikeVisitor;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter};
 
-pub fn check_crate<'hir>(hir_map: &hir::map::Map<'hir>) {
+pub fn check_crate(hir_map: &hir::map::Map<'_>) {
     hir_map.dep_graph.assert_ignored();
 
     let errors = Lock::new(Vec::new());
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 3d591c9a1c6..037d04a5d8e 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -147,7 +147,7 @@ impl Forest {
         }
     }
 
-    pub fn krate<'hir>(&'hir self) -> &'hir Crate {
+    pub fn krate(&self) -> &Crate {
         self.dep_graph.read(DepNode::new_no_params(DepKind::Krate));
         &self.krate
     }
@@ -155,7 +155,7 @@ impl Forest {
     /// This is used internally in the dependency tracking system.
     /// Use the `krate` method to ensure your dependency on the
     /// crate is tracked.
-    pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate {
+    pub fn untracked_krate(&self) -> &Crate {
         &self.krate
     }
 }
@@ -1085,7 +1085,7 @@ impl<'a> NodesMatchingSuffix<'a> {
         // If `id` itself is a mod named `m` with parent `p`, then
         // returns `Some(id, m, p)`.  If `id` has no mod in its parent
         // chain, then returns `None`.
-        fn find_first_mod_parent<'a>(map: &'a Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
+        fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
             loop {
                 if let Node::Item(item) = map.find(id)? {
                     if item_is_mod(&item) {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 6df1c2d8c77..bfbd8398f99 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -12,6 +12,7 @@ pub use self::UnsafeSource::*;
 
 use crate::hir::def::{Res, DefKind};
 use crate::hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
+use crate::hir::ptr::P;
 use crate::util::nodemap::{NodeMap, FxHashSet};
 use crate::mir::mono::Linkage;
 
@@ -23,7 +24,6 @@ use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
 use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
 use syntax::attr::{InlineAttr, OptimizeAttr};
 use syntax::ext::hygiene::SyntaxContext;
-use syntax::ptr::P;
 use syntax::symbol::{Symbol, kw};
 use syntax::tokenstream::TokenStream;
 use syntax::util::parser::ExprPrecedence;
@@ -63,6 +63,7 @@ pub mod lowering;
 pub mod map;
 pub mod pat_util;
 pub mod print;
+pub mod ptr;
 pub mod upvars;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
@@ -1979,13 +1980,15 @@ pub struct InlineAsmOutput {
     pub span: Span,
 }
 
+// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
+// it needs to be `Clone` and use plain `Vec<T>` instead of `HirVec<T>`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct InlineAsm {
     pub asm: Symbol,
     pub asm_str_style: StrStyle,
-    pub outputs: HirVec<InlineAsmOutput>,
-    pub inputs: HirVec<Symbol>,
-    pub clobbers: HirVec<Symbol>,
+    pub outputs: Vec<InlineAsmOutput>,
+    pub inputs: Vec<Symbol>,
+    pub clobbers: Vec<Symbol>,
     pub volatile: bool,
     pub alignstack: bool,
     pub dialect: AsmDialect,
@@ -2217,7 +2220,7 @@ pub enum UseKind {
 /// within the resolution map.
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct TraitRef {
-    pub path: Path,
+    pub path: P<Path>,
     // Don't hash the ref_id. It is tracked via the thing it is used to access
     #[stable_hasher(ignore)]
     pub hir_ref_id: HirId,
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 8b1984e04f5..3b33de1a179 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -6,7 +6,6 @@ use syntax::parse::lexer::comments;
 use syntax::print::pp::{self, Breaks};
 use syntax::print::pp::Breaks::{Consistent, Inconsistent};
 use syntax::print::pprust::{self, PrintState};
-use syntax::ptr::P;
 use syntax::symbol::kw;
 use syntax::util::parser::{self, AssocOp, Fixity};
 use syntax_pos::{self, BytePos, FileName};
@@ -14,6 +13,7 @@ use syntax_pos::{self, BytePos, FileName};
 use crate::hir;
 use crate::hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
 use crate::hir::{GenericParam, GenericParamKind, GenericArg};
+use crate::hir::ptr::P;
 
 use std::borrow::Cow;
 use std::cell::Cell;
diff --git a/src/librustc/hir/ptr.rs b/src/librustc/hir/ptr.rs
new file mode 100644
index 00000000000..3a87b36a1b4
--- /dev/null
+++ b/src/librustc/hir/ptr.rs
@@ -0,0 +1,141 @@
+// HACK(eddyb) this is a copy of `syntax::ptr`, minus the mutation (the HIR is
+// frozen anyway). The only reason for doing this instead of replacing `P<T>`
+// with `Box<T>` in HIR, is that `&Box<[T]>` doesn't implement `IntoIterator`.
+
+use std::fmt::{self, Display, Debug};
+use std::iter::FromIterator;
+use std::ops::Deref;
+use std::{slice, vec};
+
+use serialize::{Encodable, Decodable, Encoder, Decoder};
+
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
+/// An owned smart pointer.
+#[derive(Hash, PartialEq, Eq)]
+pub struct P<T: ?Sized> {
+    ptr: Box<T>
+}
+
+/// Construct a `P<T>` from a `T` value.
+#[allow(non_snake_case)]
+pub fn P<T: 'static>(value: T) -> P<T> {
+    P {
+        ptr: box value
+    }
+}
+
+impl<T: 'static> P<T> {
+    // HACK(eddyb) used by HIR lowering in a few places still.
+    // NOTE: do not make this more public than `pub(super)`.
+    pub(super) fn into_inner(self) -> T {
+        *self.ptr
+    }
+}
+
+impl<T: ?Sized> Deref for P<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.ptr
+    }
+}
+
+impl<T: ?Sized + Debug> Debug for P<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        Debug::fmt(&self.ptr, f)
+    }
+}
+
+impl<T: Display> Display for P<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        Display::fmt(&**self, f)
+    }
+}
+
+impl<T: 'static + Decodable> Decodable for P<T> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
+        Decodable::decode(d).map(P)
+    }
+}
+
+impl<T: Encodable> Encodable for P<T> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+
+impl<T> P<[T]> {
+    pub const fn new() -> P<[T]> {
+        // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
+        // (as trait methods, `default` in this case, can't be `const fn` yet).
+        P {
+            ptr: unsafe {
+                use std::ptr::NonNull;
+                std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
+            },
+        }
+    }
+
+    #[inline(never)]
+    pub fn from_vec(v: Vec<T>) -> P<[T]> {
+        P { ptr: v.into_boxed_slice() }
+    }
+
+    // HACK(eddyb) used by HIR lowering in a few places still.
+    // NOTE: do not make this more public than `pub(super)`,
+    // and do not make this into an `IntoIterator` impl.
+    pub(super) fn into_iter(self) -> vec::IntoIter<T> {
+        self.ptr.into_vec().into_iter()
+    }
+}
+
+
+impl<T> Default for P<[T]> {
+    /// Creates an empty `P<[T]>`.
+    fn default() -> P<[T]> {
+        P::new()
+    }
+}
+
+impl<T> From<Vec<T>> for P<[T]> {
+    fn from(v: Vec<T>) -> Self {
+        P::from_vec(v)
+    }
+}
+
+impl<T> FromIterator<T> for P<[T]> {
+    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> P<[T]> {
+        P::from_vec(iter.into_iter().collect())
+    }
+}
+
+impl<'a, T> IntoIterator for &'a P<[T]> {
+    type Item = &'a T;
+    type IntoIter = slice::Iter<'a, T>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.ptr.into_iter()
+    }
+}
+
+impl<T: Encodable> Encodable for P<[T]> {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        Encodable::encode(&**self, s)
+    }
+}
+
+impl<T: Decodable> Decodable for P<[T]> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
+        Ok(P::from_vec(Decodable::decode(d)?))
+    }
+}
+
+impl<CTX, T> HashStable<CTX> for P<T>
+    where T: ?Sized + HashStable<CTX>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        (**self).hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index b2c7bd73b68..b508f91e01e 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -23,6 +23,7 @@
 
 use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind};
+use crate::infer::region_constraints::MemberConstraint;
 use crate::mir::interpret::ConstValue;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_macros::HashStable;
@@ -189,11 +190,25 @@ pub enum CanonicalTyVarKind {
 #[derive(Clone, Debug, HashStable)]
 pub struct QueryResponse<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
-    pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
+    pub region_constraints: QueryRegionConstraints<'tcx>,
     pub certainty: Certainty,
     pub value: R,
 }
 
+#[derive(Clone, Debug, Default, HashStable)]
+pub struct QueryRegionConstraints<'tcx> {
+    pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
+    pub member_constraints: Vec<MemberConstraint<'tcx>>,
+}
+
+impl QueryRegionConstraints<'_> {
+    /// Represents an empty (trivially true) set of region
+    /// constraints.
+    pub fn is_empty(&self) -> bool {
+        self.outlives.is_empty() && self.member_constraints.is_empty()
+    }
+}
+
 pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
 
 pub type CanonicalizedQueryResponse<'tcx, T> =
@@ -292,7 +307,8 @@ impl<'tcx, V> Canonical<'tcx, V> {
     }
 }
 
-pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
+pub type QueryOutlivesConstraint<'tcx> =
+    ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
 
 impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// Creates a substitution S for the canonical value with fresh
@@ -540,6 +556,19 @@ BraceStructLiftImpl! {
     } where R: Lift<'tcx>
 }
 
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
+        outlives, member_constraints
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
+        type Lifted = QueryRegionConstraints<'tcx>;
+        outlives, member_constraints
+    }
+}
+
 impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
     type Output = Kind<'tcx>;
 
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 3e92fed005c..79c5538626b 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -11,7 +11,7 @@ use crate::arena::ArenaAllocatable;
 use crate::infer::canonical::substitute::substitute_value;
 use crate::infer::canonical::{
     Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty,
-    OriginalQueryValues, QueryRegionConstraint, QueryResponse,
+    OriginalQueryValues, QueryRegionConstraints, QueryOutlivesConstraint, QueryResponse,
 };
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxtBuilder;
@@ -132,7 +132,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     {
         self.canonicalize_response(&QueryResponse {
             var_values: inference_vars,
-            region_constraints: vec![],
+            region_constraints: QueryRegionConstraints::default(),
             certainty: Certainty::Proven, // Ambiguities are OK!
             value: answer,
         })
@@ -174,7 +174,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
         let region_obligations = self.take_registered_region_obligations();
         let region_constraints = self.with_region_constraints(|region_constraints| {
-            make_query_outlives(
+            make_query_region_constraints(
                 tcx,
                 region_obligations
                     .iter()
@@ -222,10 +222,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
             mut obligations,
         } = self.query_response_substitution(cause, param_env, original_values, query_response)?;
 
-        obligations.extend(self.query_region_constraints_into_obligations(
+        obligations.extend(self.query_outlives_constraints_into_obligations(
             cause,
             param_env,
-            &query_response.value.region_constraints,
+            &query_response.value.region_constraints.outlives,
             &result_subst,
         ));
 
@@ -248,9 +248,9 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     /// that come out of these queries, which it wants to convert into
     /// MIR-based constraints and solve. Therefore, it is most
     /// convenient for the NLL Type Checker to **directly consume**
-    /// the `QueryRegionConstraint` values that arise from doing a
+    /// the `QueryOutlivesConstraint` values that arise from doing a
     /// query. This is contrast to other parts of the compiler, which
-    /// would prefer for those `QueryRegionConstraint` to be converted
+    /// would prefer for those `QueryOutlivesConstraint` to be converted
     /// into the older infcx-style constraints (e.g., calls to
     /// `sub_regions` or `register_region_obligation`).
     ///
@@ -263,7 +263,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ///   result. If any errors arise, they are propagated back as an
     ///   `Err` result.
     /// - In the case of a successful substitution, we will append
-    ///   `QueryRegionConstraint` values onto the
+    ///   `QueryOutlivesConstraint` values onto the
     ///   `output_query_region_constraints` vector for the solver to
     ///   use (if an error arises, some values may also be pushed, but
     ///   they should be ignored).
@@ -279,7 +279,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         original_values: &OriginalQueryValues<'tcx>,
         query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
-        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
     ) -> InferResult<'tcx, R>
     where
         R: Debug + TypeFoldable<'tcx>,
@@ -287,7 +287,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         let result_subst =
             self.query_response_substitution_guess(cause, original_values, query_response);
 
-        // Compute `QueryRegionConstraint` values that unify each of
+        // Compute `QueryOutlivesConstraint` values that unify each of
         // the original values `v_o` that was canonicalized into a
         // variable...
         let mut obligations = vec![];
@@ -306,8 +306,10 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                     // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
                     if v_o != v_r {
                         output_query_region_constraints
+                            .outlives
                             .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
                         output_query_region_constraints
+                            .outlives
                             .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
                     }
                 }
@@ -333,12 +335,12 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         }
 
         // ...also include the other query region constraints from the query.
-        output_query_region_constraints.extend(
-            query_response.value.region_constraints.iter().filter_map(|r_c| {
+        output_query_region_constraints.outlives.extend(
+            query_response.value.region_constraints.outlives.iter().filter_map(|r_c| {
                 let r_c = substitute_value(self.tcx, &result_subst, r_c);
 
                 // Screen out `'a: 'a` cases -- we skip the binder here but
-                // only care the inner values to one another, so they are still at
+                // only compare the inner values to one another, so they are still at
                 // consistent binding levels.
                 let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
                 if k1 != r2.into() {
@@ -349,6 +351,13 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
             })
         );
 
+        // ...also include the query member constraints.
+        output_query_region_constraints.member_constraints.extend(
+            query_response.value.region_constraints.member_constraints.iter().map(|p_c| {
+                substitute_value(self.tcx, &result_subst, p_c)
+            })
+        );
+
         let user_result: R =
             query_response.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
 
@@ -560,11 +569,11 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
     /// Converts the region constraints resulting from a query into an
     /// iterator of obligations.
-    fn query_region_constraints_into_obligations<'a>(
+    fn query_outlives_constraints_into_obligations<'a>(
         &'a self,
         cause: &'a ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
+        unsubstituted_region_constraints: &'a [QueryOutlivesConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
     ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a + Captures<'tcx> {
         unsubstituted_region_constraints
@@ -645,15 +654,16 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
 /// Given the region obligations and constraints scraped from the infcx,
 /// creates query region constraints.
-pub fn make_query_outlives<'tcx>(
+pub fn make_query_region_constraints<'tcx>(
     tcx: TyCtxt<'tcx>,
     outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>)>,
     region_constraints: &RegionConstraintData<'tcx>,
-) -> Vec<QueryRegionConstraint<'tcx>> {
+) -> QueryRegionConstraints<'tcx> {
     let RegionConstraintData {
         constraints,
         verifys,
         givens,
+        member_constraints,
     } = region_constraints;
 
     assert!(verifys.is_empty());
@@ -684,5 +694,5 @@ pub fn make_query_outlives<'tcx>(
         )
         .collect();
 
-    outlives
+    QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
 }
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 65225163a25..cbfb048c064 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -53,6 +53,7 @@ use crate::infer::{self, SuppressRegionErrors};
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::hir::Node;
+use crate::infer::opaque_types;
 use crate::middle::region;
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::error::TypeError;
@@ -375,6 +376,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             );
                         }
                     }
+
+                    RegionResolutionError::MemberConstraintFailure {
+                        opaque_type_def_id,
+                        hidden_ty,
+                        member_region,
+                        span: _,
+                        choice_regions: _,
+                    } => {
+                        let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
+                        opaque_types::unexpected_hidden_region_diagnostic(
+                            self.tcx,
+                            Some(region_scope_tree),
+                            opaque_type_def_id,
+                            hidden_ty,
+                            member_region,
+                        ).emit();
+                    }
                 }
             }
         }
@@ -411,7 +429,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
             RegionResolutionError::GenericBoundFailure(..) => true,
             RegionResolutionError::ConcreteFailure(..)
-            | RegionResolutionError::SubSupConflict(..) => false,
+                | RegionResolutionError::SubSupConflict(..)
+                | RegionResolutionError::MemberConstraintFailure { .. } => false,
         };
 
         let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
@@ -429,6 +448,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
             RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
             RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
+            RegionResolutionError::MemberConstraintFailure { span, .. } => span,
         });
         errors
     }
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 2613f4c7c2a..d06c4434b3a 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -1,13 +1,20 @@
 //! Lexical region resolution.
 
+use crate::hir::def_id::DefId;
 use crate::infer::region_constraints::Constraint;
 use crate::infer::region_constraints::GenericKind;
+use crate::infer::region_constraints::MemberConstraint;
 use crate::infer::region_constraints::RegionConstraintData;
 use crate::infer::region_constraints::VarInfos;
 use crate::infer::region_constraints::VerifyBound;
 use crate::infer::RegionVariableOrigin;
 use crate::infer::SubregionOrigin;
 use crate::middle::free_region::RegionRelations;
+use crate::ty::fold::TypeFoldable;
+use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
+use crate::ty::{ReLateBound, RePlaceholder, ReScope, ReVar};
+use crate::ty::{Region, RegionVid};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::implementation::{
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
@@ -15,12 +22,7 @@ use rustc_data_structures::graph::implementation::{
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use smallvec::SmallVec;
 use std::fmt;
-use std::u32;
-use crate::ty::fold::TypeFoldable;
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
-use crate::ty::{ReLateBound, ReScope, RePlaceholder, ReVar};
-use crate::ty::{Region, RegionVid};
+use syntax_pos::Span;
 
 mod graphviz;
 
@@ -36,11 +38,7 @@ pub fn resolve<'tcx>(
 ) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
     debug!("RegionConstraintData: resolve_regions()");
     let mut errors = vec![];
-    let mut resolver = LexicalResolver {
-        region_rels,
-        var_infos,
-        data,
-    };
+    let mut resolver = LexicalResolver { region_rels, var_infos, data };
     let values = resolver.infer_variable_values(&mut errors);
     (values, errors)
 }
@@ -84,6 +82,17 @@ pub enum RegionResolutionError<'tcx> {
         SubregionOrigin<'tcx>,
         Region<'tcx>,
     ),
+
+    /// Indicates a failure of a `MemberConstraint`. These arise during
+    /// impl trait processing explicitly -- basically, the impl trait's hidden type
+    /// included some region that it was not supposed to.
+    MemberConstraintFailure {
+        span: Span,
+        opaque_type_def_id: DefId,
+        hidden_ty: Ty<'tcx>,
+        member_region: Region<'tcx>,
+        choice_regions: Vec<Region<'tcx>>,
+    },
 }
 
 struct RegionAndOrigin<'tcx> {
@@ -121,7 +130,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
         let graph = self.construct_graph();
         self.expand_givens(&graph);
-        self.expansion(&mut var_data);
+        loop {
+            self.expansion(&mut var_data);
+            if !self.enforce_member_constraints(&graph, &mut var_data) {
+                break;
+            }
+        }
         self.collect_errors(&mut var_data, errors);
         self.collect_var_errors(&var_data, &graph, errors);
         var_data
@@ -136,7 +150,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
     fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
         LexicalRegionResolutions {
             error_region: tcx.lifetimes.re_static,
-            values: IndexVec::from_elem_n(VarValue::Value(tcx.lifetimes.re_empty), self.num_vars())
+            values: IndexVec::from_elem_n(VarValue::Value(tcx.lifetimes.re_empty), self.num_vars()),
         }
     }
 
@@ -182,6 +196,113 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// Enforce all member constraints and return true if anything
+    /// changed. See `enforce_member_constraint` for more details.
+    fn enforce_member_constraints(
+        &self,
+        graph: &RegionGraph<'tcx>,
+        var_values: &mut LexicalRegionResolutions<'tcx>,
+    ) -> bool {
+        // Note: we don't use the `any` combinator because we don't
+        // want to stop at the first constraint that makes a change.
+        let mut any_changed = false;
+        for member_constraint in &self.data.member_constraints {
+            if self.enforce_member_constraint(graph, member_constraint, var_values) {
+                any_changed = true;
+            }
+        }
+        any_changed
+    }
+
+    /// Enforce a constraint like
+    ///
+    /// ```
+    /// 'r member of ['c...]
+    /// ```
+    ///
+    /// We look for all choice regions from the list `'c...` that:
+    ///
+    /// (a) are greater than the current value of `'r` (which is a lower bound)
+    ///
+    /// and
+    ///
+    /// (b) are compatible with the upper bounds of `'r` that we can
+    /// find by traversing the graph.
+    ///
+    /// From that list, we look for a *minimal* option `'c_min`. If we
+    /// find one, then we can enforce that `'r: 'c_min`.
+    fn enforce_member_constraint(
+        &self,
+        graph: &RegionGraph<'tcx>,
+        member_constraint: &MemberConstraint<'tcx>,
+        var_values: &mut LexicalRegionResolutions<'tcx>,
+    ) -> bool {
+        debug!("enforce_member_constraint(member_constraint={:#?})", member_constraint);
+
+        // The constraint is some inference variable (`vid`) which
+        // must be equal to one of the options.
+        let member_vid = match member_constraint.member_region {
+            ty::ReVar(vid) => *vid,
+            _ => return false,
+        };
+
+        // The current value of `vid` is a lower bound LB -- i.e., we
+        // know that `LB <= vid` must be true.
+        let member_lower_bound: ty::Region<'tcx> = match var_values.value(member_vid) {
+            VarValue::ErrorValue => return false,
+            VarValue::Value(r) => r,
+        };
+
+        // Find all the "upper bounds" -- that is, each region `b` such that
+        // `r0 <= b` must hold.
+        let (member_upper_bounds, _) = self.collect_concrete_regions(
+            graph,
+            member_vid,
+            OUTGOING,
+            None,
+        );
+
+        // Get an iterator over the *available choice* -- that is,
+        // each choice region `c` where `lb <= c` and `c <= ub` for all the
+        // upper bounds `ub`.
+        debug!("enforce_member_constraint: upper_bounds={:#?}", member_upper_bounds);
+        let mut options = member_constraint.choice_regions.iter().filter(|option| {
+            self.sub_concrete_regions(member_lower_bound, option)
+                && member_upper_bounds
+                    .iter()
+                    .all(|upper_bound| self.sub_concrete_regions(option, upper_bound.region))
+        });
+
+        // If there is more than one option, we only make a choice if
+        // there is a single *least* choice -- i.e., some available
+        // region that is `<=` all the others.
+        let mut least_choice: ty::Region<'tcx> = match options.next() {
+            Some(&r) => r,
+            None => return false,
+        };
+        debug!("enforce_member_constraint: least_choice={:?}", least_choice);
+        for &option in options {
+            debug!("enforce_member_constraint: option={:?}", option);
+            if !self.sub_concrete_regions(least_choice, option) {
+                if self.sub_concrete_regions(option, least_choice) {
+                    debug!("enforce_member_constraint: new least choice");
+                    least_choice = option;
+                } else {
+                    debug!("enforce_member_constraint: no least choice");
+                    return false;
+                }
+            }
+        }
+
+        debug!("enforce_member_constraint: final least choice = {:?}", least_choice);
+        if least_choice != member_lower_bound {
+            *var_values.value_mut(member_vid) = VarValue::Value(least_choice);
+            true
+        } else {
+            false
+        }
+    }
+
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
         self.iterate_until_fixed_point("Expansion", |constraint| {
             debug!("expansion: constraint={:?}", constraint);
@@ -196,7 +317,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                         let b_data = var_values.value_mut(b_vid);
                         let retain = match *b_data {
                             VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
-                            _ => true
+                            _ => true,
                         };
                         (a_region, b_vid, b_data, retain)
                     }
@@ -204,7 +325,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    return (false, false)
+                    return (false, false);
                 }
             };
 
@@ -226,16 +347,16 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
         match *a_region {
             // Check if this relationship is implied by a given.
-            ty::ReEarlyBound(_) | ty::ReFree(_) => if self.data.givens.contains(&(a_region, b_vid))
-            {
-                debug!("given");
-                return false;
-            },
+            ty::ReEarlyBound(_) | ty::ReFree(_) => {
+                if self.data.givens.contains(&(a_region, b_vid)) {
+                    debug!("given");
+                    return false;
+                }
+            }
 
             _ => {}
         }
 
-
         match *b_data {
             VarValue::Value(cur_region) => {
                 // Identical scopes can show up quite often, if the fixed point
@@ -267,10 +388,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     }
                 }
 
-                debug!(
-                    "Expanding value of {:?} from {:?} to {:?}",
-                    b_vid, cur_region, lub
-                );
+                debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
 
                 *b_data = VarValue::Value(lub);
                 return true;
@@ -282,6 +400,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// True if `a <= b`, but not defined over inference variables.
+    fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
+        self.lub_concrete_regions(a, b) == b
+    }
+
+    /// Returns the smallest region `c` such that `a <= c` and `b <= c`.
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
         let tcx = self.tcx();
 
@@ -321,17 +445,16 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 // at least as big as fr.scope".  So, we can
                 // reasonably compare free regions and scopes:
                 let fr_scope = match (a, b) {
-                    (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => self.region_rels
-                        .region_scope_tree
-                        .early_free_scope(self.tcx(), br),
-                    (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => self.region_rels
-                        .region_scope_tree
-                        .free_scope(self.tcx(), fr),
+                    (&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
+                        self.region_rels.region_scope_tree.early_free_scope(self.tcx(), br)
+                    }
+                    (&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
+                        self.region_rels.region_scope_tree.free_scope(self.tcx(), fr)
+                    }
                     _ => bug!(),
                 };
-                let r_id = self.region_rels
-                    .region_scope_tree
-                    .nearest_common_ancestor(fr_scope, s_id);
+                let r_id =
+                    self.region_rels.region_scope_tree.nearest_common_ancestor(fr_scope, s_id);
                 if r_id == fr_scope {
                     // if the free region's scope `fr.scope` is bigger than
                     // the scope region `s_id`, then the LUB is the free
@@ -352,9 +475,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 // The region corresponding to an outer block is a
                 // subtype of the region corresponding to an inner
                 // block.
-                let lub = self.region_rels
-                    .region_scope_tree
-                    .nearest_common_ancestor(a_id, b_id);
+                let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
                 tcx.mk_region(ReScope(lub))
             }
 
@@ -365,11 +486,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
             // For these types, we cannot define any additional
             // relationship:
-            (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => if a == b {
-                a
-            } else {
-                tcx.lifetimes.re_static
-            },
+            (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => {
+                if a == b {
+                    a
+                } else {
+                    tcx.lifetimes.re_static
+                }
+            }
         }
     }
 
@@ -382,10 +505,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         errors: &mut Vec<RegionResolutionError<'tcx>>,
     ) {
         for (constraint, origin) in &self.data.constraints {
-            debug!(
-                "collect_errors: constraint={:?} origin={:?}",
-                constraint, origin
-            );
+            debug!("collect_errors: constraint={:?} origin={:?}", constraint, origin);
             match *constraint {
                 Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
                     // Expansion will ensure that these constraints hold. Ignore.
@@ -433,6 +553,25 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
         }
 
+        // Check that all member constraints are satisfied.
+        for member_constraint in &self.data.member_constraints {
+            let member_region = var_data.normalize(self.tcx(), member_constraint.member_region);
+            let choice_regions = member_constraint
+                .choice_regions
+                .iter()
+                .map(|&choice_region| var_data.normalize(self.tcx(), choice_region));
+            if !choice_regions.clone().any(|choice_region| member_region == choice_region) {
+                let span = self.tcx().def_span(member_constraint.opaque_type_def_id);
+                errors.push(RegionResolutionError::MemberConstraintFailure {
+                    span,
+                    opaque_type_def_id: member_constraint.opaque_type_def_id,
+                    hidden_ty: member_constraint.hidden_ty,
+                    member_region,
+                    choice_regions: choice_regions.collect(),
+                });
+            }
+        }
+
         for verify in &self.data.verifys {
             debug!("collect_errors: verify={:?}", verify);
             let sub = var_data.normalize(self.tcx(), verify.region);
@@ -483,34 +622,35 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         // idea is to report errors that derive from independent
         // regions of the graph, but not those that derive from
         // overlapping locations.
-        let mut dup_vec = vec![u32::MAX; self.num_vars()];
+        let mut dup_vec = IndexVec::from_elem_n(None, self.num_vars());
 
         for (node_vid, value) in var_data.values.iter_enumerated() {
             match *value {
                 VarValue::Value(_) => { /* Inference successful */ }
                 VarValue::ErrorValue => {
-                    /* Inference impossible: this value contains
-                       inconsistent constraints.
-
-                       I think that in this case we should report an
-                       error now -- unlike the case above, we can't
-                       wait to see whether the user needs the result
-                       of this variable. The reason is that the mere
-                       existence of this variable implies that the
-                       region graph is inconsistent, whether or not it
-                       is used.
-
-                       For example, we may have created a region
-                       variable that is the GLB of two other regions
-                       which do not have a GLB. Even if that variable
-                       is not used, it implies that those two regions
-                       *should* have a GLB.
-
-                       At least I think this is true. It may be that
-                       the mere existence of a conflict in a region variable
-                       that is not used is not a problem, so if this rule
-                       starts to create problems we'll have to revisit
-                       this portion of the code and think hard about it. =) */
+                    // Inference impossible: this value contains
+                    // inconsistent constraints.
+                    //
+                    // I think that in this case we should report an
+                    // error now -- unlike the case above, we can't
+                    // wait to see whether the user needs the result
+                    // of this variable. The reason is that the mere
+                    // existence of this variable implies that the
+                    // region graph is inconsistent, whether or not it
+                    // is used.
+                    //
+                    // For example, we may have created a region
+                    // variable that is the GLB of two other regions
+                    // which do not have a GLB. Even if that variable
+                    // is not used, it implies that those two regions
+                    // *should* have a GLB.
+                    //
+                    // At least I think this is true. It may be that
+                    // the mere existence of a conflict in a region
+                    // variable that is not used is not a problem, so
+                    // if this rule starts to create problems we'll
+                    // have to revisit this portion of the code and
+                    // think hard about it. =) -- nikomatsakis
                     self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
                 }
             }
@@ -562,16 +702,16 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
     fn collect_error_for_expanding_node(
         &self,
         graph: &RegionGraph<'tcx>,
-        dup_vec: &mut [u32],
+        dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
         node_idx: RegionVid,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
     ) {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
         let (mut lower_bounds, lower_dup) =
-            self.collect_concrete_regions(graph, node_idx, INCOMING, dup_vec);
+            self.collect_concrete_regions(graph, node_idx, INCOMING, Some(dup_vec));
         let (mut upper_bounds, upper_dup) =
-            self.collect_concrete_regions(graph, node_idx, OUTGOING, dup_vec);
+            self.collect_concrete_regions(graph, node_idx, OUTGOING, Some(dup_vec));
 
         if lower_dup || upper_dup {
             return;
@@ -604,9 +744,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             };
 
             for upper_bound in &upper_bounds {
-                if !self.region_rels
-                    .is_subregion_of(effective_lower_bound, upper_bound.region)
-                {
+                if !self.region_rels.is_subregion_of(effective_lower_bound, upper_bound.region) {
                     let origin = self.var_infos[node_idx].origin.clone();
                     debug!(
                         "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
@@ -643,7 +781,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         graph: &RegionGraph<'tcx>,
         orig_node_idx: RegionVid,
         dir: Direction,
-        dup_vec: &mut [u32],
+        mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
     ) -> (Vec<RegionAndOrigin<'tcx>>, bool) {
         struct WalkState<'tcx> {
             set: FxHashSet<RegionVid>,
@@ -667,23 +805,23 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             let node_idx = state.stack.pop().unwrap();
 
             // check whether we've visited this node on some previous walk
-            if dup_vec[node_idx.index() as usize] == u32::MAX {
-                dup_vec[node_idx.index() as usize] = orig_node_idx.index() as u32;
-            } else if dup_vec[node_idx.index() as usize] != orig_node_idx.index() as u32 {
-                state.dup_found = true;
-            }
+            if let Some(dup_vec) = &mut dup_vec {
+                if dup_vec[node_idx].is_none() {
+                    dup_vec[node_idx] = Some(orig_node_idx);
+                } else if dup_vec[node_idx] != Some(orig_node_idx) {
+                    state.dup_found = true;
+                }
 
-            debug!(
-                "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
-                orig_node_idx, node_idx
-            );
+                debug!(
+                    "collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
+                    orig_node_idx, node_idx
+                );
+            }
 
             process_edges(&self.data, &mut state, graph, node_idx, dir);
         }
 
-        let WalkState {
-            result, dup_found, ..
-        } = state;
+        let WalkState { result, dup_found, .. } = state;
         return (result, dup_found);
 
         fn process_edges<'tcx>(
@@ -699,11 +837,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
                 match edge.data {
                     Constraint::VarSubVar(from_vid, to_vid) => {
-                        let opp_vid = if from_vid == source_vid {
-                            to_vid
-                        } else {
-                            from_vid
-                        };
+                        let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
                         if state.set.insert(opp_vid) {
                             state.stack.push(opp_vid);
                         }
@@ -726,7 +860,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
     }
 
     fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
-        where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
+    where
+        F: FnMut(&Constraint<'tcx>) -> (bool, bool),
     {
         let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
         let mut iteration = 0;
@@ -760,17 +895,17 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     && self.bound_is_met(b, var_values, generic_ty, min)
             }
 
-            VerifyBound::OutlivedBy(r) =>
-                self.region_rels.is_subregion_of(
-                    min,
-                    var_values.normalize(self.tcx(), r),
-                ),
+            VerifyBound::OutlivedBy(r) => {
+                self.region_rels.is_subregion_of(min, var_values.normalize(self.tcx(), r))
+            }
 
-            VerifyBound::AnyBound(bs) => bs.iter()
-                .any(|b| self.bound_is_met(b, var_values, generic_ty, min)),
+            VerifyBound::AnyBound(bs) => {
+                bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
+            }
 
-            VerifyBound::AllBounds(bs) => bs.iter()
-                .all(|b| self.bound_is_met(b, var_values, generic_ty, min)),
+            VerifyBound::AllBounds(bs) => {
+                bs.iter().all(|b| self.bound_is_met(b, var_values, generic_ty, min))
+            }
         }
     }
 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 9a5c726901f..663acd67dcd 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -26,6 +26,7 @@ use crate::ty::{FloatVid, IntVid, TyVid, ConstVid};
 use crate::util::nodemap::FxHashMap;
 
 use errors::DiagnosticBuilder;
+use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
 use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::collections::BTreeMap;
@@ -904,6 +905,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             .make_subregion(origin, a, b);
     }
 
+    /// Require that the region `r` be equal to one of the regions in
+    /// the set `regions`.
+    pub fn member_constraint(
+        &self,
+        opaque_type_def_id: DefId,
+        definition_span: Span,
+        hidden_ty: Ty<'tcx>,
+        region: ty::Region<'tcx>,
+        in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
+    ) {
+        debug!("member_constraint({:?} <: {:?})", region, in_regions);
+        self.borrow_region_constraints()
+            .member_constraint(opaque_type_def_id, definition_span, hidden_ty, region, in_regions);
+    }
+
     pub fn subtype_predicate(
         &self,
         cause: &ObligationCause<'tcx>,
@@ -1456,7 +1472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // Even if the type may have no inference variables, during
         // type-checking closure types are in local tables only.
         if !self.in_progress_tables.is_some() || !ty.has_closure_types() {
-            if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
+            if !(param_env, ty).has_local_value() {
                 return ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span);
             }
         }
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index a1a93eb5521..a0621af0537 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -364,7 +364,7 @@ where
         // been fully instantiated and hence the set of scopes we have
         // doesn't matter -- just to be sure, put an empty vector
         // in there.
-        let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
+        let old_a_scopes = ::std::mem::take(pair.vid_scopes(self));
 
         // Relate the generalized kind to the original one.
         let result = pair.relate_generalized_ty(self, generalized_ty);
diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
index 6b6dbd43167..f43e3fa0b77 100644
--- a/src/librustc/infer/opaque_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -1,16 +1,19 @@
-use rustc_data_structures::fx::FxHashMap;
-use syntax_pos::Span;
-
-use crate::hir::def_id::DefId;
 use crate::hir;
+use crate::hir::def_id::DefId;
 use crate::hir::Node;
-use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::outlives::free_region_map::FreeRegionRelations;
+use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind};
+use crate::middle::region;
 use crate::traits::{self, PredicateObligation};
-use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind};
 use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, UnpackedKind};
+use crate::ty::subst::{InternalSubsts, Kind, SubstsRef, UnpackedKind};
+use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt};
 use crate::util::nodemap::DefIdMap;
+use errors::DiagnosticBuilder;
+use rustc::session::config::nightly_options;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::Lrc;
+use syntax_pos::Span;
 
 pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
 
@@ -32,6 +35,20 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// then `substs` would be `['a, T]`.
     pub substs: SubstsRef<'tcx>,
 
+    /// The span of this particular definition of the opaque type.  So
+    /// for example:
+    ///
+    /// ```
+    /// existential type Foo;
+    /// fn bar() -> Foo {
+    ///             ^^^ This is the span we are looking for!
+    /// ```
+    ///
+    /// In cases where the fn returns `(impl Trait, impl Trait)` or
+    /// other such combinations, the result is currently
+    /// over-approximated, but better than nothing.
+    pub definition_span: Span,
+
     /// The type variable that represents the value of the abstract type
     /// that we require. In other words, after we compile this function,
     /// we will be created a constraint like:
@@ -98,30 +115,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// - `param_env` -- the in-scope parameter environment to be used for
     ///   obligations
     /// - `value` -- the value within which we are instantiating opaque types
+    /// - `value_span` -- the span where the value came from, used in error reporting
     pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
         parent_def_id: DefId,
         body_id: hir::HirId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
+        value_span: Span,
     ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
-        debug!("instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
-                param_env={:?})",
-               value, parent_def_id, body_id, param_env,
+        debug!(
+            "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
+             param_env={:?})",
+            value, parent_def_id, body_id, param_env,
         );
         let mut instantiator = Instantiator {
             infcx: self,
             parent_def_id,
             body_id,
             param_env,
+            value_span,
             opaque_types: Default::default(),
             obligations: vec![],
         };
         let value = instantiator.instantiate_opaque_types_in_map(value);
-        InferOk {
-            value: (value, instantiator.opaque_types),
-            obligations: instantiator.obligations,
-        }
+        InferOk { value: (value, instantiator.opaque_types), obligations: instantiator.obligations }
     }
 
     /// Given the map `opaque_types` containing the existential `impl
@@ -216,13 +234,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     ///
     /// # The Solution
     ///
-    /// We make use of the constraint that we *do* have in the `<=`
-    /// relation. To do that, we find the "minimum" of all the
-    /// arguments that appear in the substs: that is, some region
-    /// which is less than all the others. In the case of `Foo1<'a>`,
-    /// that would be `'a` (it's the only choice, after all). Then we
-    /// apply that as a least bound to the variables (e.g., `'a <=
-    /// '0`).
+    /// We generally prefer to make `<=` constraints, since they
+    /// integrate best into the region solver. To do that, we find the
+    /// "minimum" of all the arguments that appear in the substs: that
+    /// is, some region which is less than all the others. In the case
+    /// of `Foo1<'a>`, that would be `'a` (it's the only choice, after
+    /// all). Then we apply that as a least bound to the variables
+    /// (e.g., `'a <= '0`).
     ///
     /// In some cases, there is no minimum. Consider this example:
     ///
@@ -230,8 +248,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
     /// ```
     ///
-    /// Here we would report an error, because `'a` and `'b` have no
-    /// relation to one another.
+    /// Here we would report a more complex "in constraint", like `'r
+    /// in ['a, 'b, 'static]` (where `'r` is some regon appearing in
+    /// the hidden type).
+    ///
+    /// # Constrain regions, not the hidden concrete type
+    ///
+    /// Note that generating constraints on each region `Rc` is *not*
+    /// the same as generating an outlives constraint on `Tc` iself.
+    /// For example, if we had a function like this:
+    ///
+    /// ```rust
+    /// fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> {
+    ///   (x, y)
+    /// }
+    ///
+    /// // Equivalent to:
+    /// existential type FooReturn<'a, T>: Foo<'a>;
+    /// fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
+    /// ```
+    ///
+    /// then the hidden type `Tc` would be `(&'0 u32, T)` (where `'0`
+    /// is an inference variable). If we generated a constraint that
+    /// `Tc: 'a`, then this would incorrectly require that `T: 'a` --
+    /// but this is not necessary, because the existential type we
+    /// create will be allowed to reference `T`. So we only generate a
+    /// constraint that `'0: 'a`.
     ///
     /// # The `free_region_relations` parameter
     ///
@@ -274,6 +316,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
+    /// See `constrain_opaque_types` for documentation.
     pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         def_id: DefId,
@@ -290,32 +333,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
 
-        let abstract_type_generics = tcx.generics_of(def_id);
+        let opaque_type_generics = tcx.generics_of(def_id);
 
         let span = tcx.def_span(def_id);
 
         // If there are required region bounds, we can use them.
         if opaque_defn.has_required_region_bounds {
             let predicates_of = tcx.predicates_of(def_id);
-            debug!(
-                "constrain_opaque_type: predicates: {:#?}",
-                predicates_of,
-            );
+            debug!("constrain_opaque_type: predicates: {:#?}", predicates_of,);
             let bounds = predicates_of.instantiate(tcx, opaque_defn.substs);
             debug!("constrain_opaque_type: bounds={:#?}", bounds);
             let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
 
-            let required_region_bounds = tcx.required_region_bounds(
-                opaque_type,
-                bounds.predicates,
-            );
+            let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates);
             debug_assert!(!required_region_bounds.is_empty());
 
-            for region in required_region_bounds {
-                concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor {
-                    infcx: self,
-                    least_region: region,
-                    span,
+            for required_region in required_region_bounds {
+                concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+                    tcx: self.tcx,
+                    op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
                 });
             }
             return;
@@ -329,11 +365,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // `['a]` for the first impl trait and `'b` for the
         // second.
         let mut least_region = None;
-        for param in &abstract_type_generics.params {
+        for param in &opaque_type_generics.params {
             match param.kind {
                 GenericParamDefKind::Lifetime => {}
-                _ => continue
+                _ => continue,
             }
+
             // Get the value supplied for this region from the substs.
             let subst_arg = opaque_defn.substs.region_at(param.index as usize);
 
@@ -350,44 +387,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         least_region = Some(subst_arg);
                     } else {
                         // There are two regions (`lr` and
-                        // `subst_arg`) which are not relatable. We can't
-                        // find a best choice.
-                        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, &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;
+                        // `subst_arg`) which are not relatable. We
+                        // can't find a best choice. Therefore,
+                        // instead of creating a single bound like
+                        // `'r: 'a` (which is our preferred choice),
+                        // we will create a "in bound" like `'r in
+                        // ['a, 'b, 'c]`, where `'a..'c` are the
+                        // regions that appear in the impl trait.
+                        return self.generate_member_constraint(
+                            concrete_ty,
+                            opaque_type_generics,
+                            opaque_defn,
+                            def_id,
+                            lr,
+                            subst_arg,
+                        );
                     }
                 }
             }
@@ -396,13 +410,121 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let least_region = least_region.unwrap_or(tcx.lifetimes.re_static);
         debug!("constrain_opaque_types: least_region={:?}", least_region);
 
-        concrete_ty.visit_with(&mut OpaqueTypeOutlivesVisitor {
-            infcx: self,
-            least_region,
-            span,
+        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
+            op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
         });
     }
 
+    /// As a fallback, we sometimes generate an "in constraint". For
+    /// a case like `impl Foo<'a, 'b>`, where `'a` and `'b` cannot be
+    /// related, we would generate a constraint `'r in ['a, 'b,
+    /// 'static]` for each region `'r` that appears in the hidden type
+    /// (i.e., it must be equal to `'a`, `'b`, or `'static`).
+    ///
+    /// `conflict1` and `conflict2` are the two region bounds that we
+    /// detected which were unrelated. They are used for diagnostics.
+    fn generate_member_constraint(
+        &self,
+        concrete_ty: Ty<'tcx>,
+        opaque_type_generics: &ty::Generics,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+        conflict1: ty::Region<'tcx>,
+        conflict2: ty::Region<'tcx>,
+    ) {
+        // For now, enforce a feature gate outside of async functions.
+        if self.member_constraint_feature_gate(
+            opaque_defn,
+            opaque_type_def_id,
+            conflict1,
+            conflict2,
+        ) {
+            return;
+        }
+
+        // Create the set of choice regions: each region in the hidden
+        // type can be equal to any of the region parameters of the
+        // opaque type definition.
+        let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
+            opaque_type_generics
+                .params
+                .iter()
+                .filter(|param| match param.kind {
+                    GenericParamDefKind::Lifetime => true,
+                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
+                })
+                .map(|param| opaque_defn.substs.region_at(param.index as usize))
+                .chain(std::iter::once(self.tcx.lifetimes.re_static))
+                .collect(),
+        );
+
+        concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
+            op: |r| self.member_constraint(
+                opaque_type_def_id,
+                opaque_defn.definition_span,
+                concrete_ty,
+                r,
+                &choice_regions,
+            ),
+        });
+    }
+
+    /// Member constraints are presently feature-gated except for
+    /// async-await. We expect to lift this once we've had a bit more
+    /// time.
+    fn member_constraint_feature_gate(
+        &self,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
+        opaque_type_def_id: DefId,
+        conflict1: ty::Region<'tcx>,
+        conflict2: ty::Region<'tcx>,
+    ) -> bool {
+        // If we have `#![feature(member_constraints)]`, no problems.
+        if self.tcx.features().member_constraints {
+            return false;
+        }
+
+        let span = self.tcx.def_span(opaque_type_def_id);
+
+        // Without a feature-gate, we only generate member-constraints for async-await.
+        let context_name = match opaque_defn.origin {
+            // No feature-gate required for `async fn`.
+            hir::ExistTyOrigin::AsyncFn => return false,
+
+            // Otherwise, generate the label we'll use in the error message.
+            hir::ExistTyOrigin::ExistentialType => "existential type",
+            hir::ExistTyOrigin::ReturnImplTrait => "impl Trait",
+        };
+        let msg = format!("ambiguous lifetime bound in `{}`", context_name);
+        let mut err = self.tcx.sess.struct_span_err(span, &msg);
+
+        let conflict1_name = conflict1.to_string();
+        let conflict2_name = conflict2.to_string();
+        let label_owned;
+        let label = match (&*conflict1_name, &*conflict2_name) {
+            ("'_", "'_") => "the elided lifetimes here do not outlive one another",
+            _ => {
+                label_owned = format!(
+                    "neither `{}` nor `{}` outlives the other",
+                    conflict1_name, conflict2_name,
+                );
+                &label_owned
+            }
+        };
+        err.span_label(span, label);
+
+        if nightly_options::is_nightly_build() {
+            help!(err,
+                  "add #![feature(member_constraints)] to the crate attributes \
+                   to enable");
+        }
+
+        err.emit();
+        true
+    }
+
     /// Given the fully resolved, instantiated type for an opaque
     /// type, i.e., the value of an inference variable like C1 or C2
     /// (*), computes the "definition type" for an abstract type
@@ -456,23 +578,98 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // Convert the type from the function into a type valid outside
         // the function, by replacing invalid regions with 'static,
         // after producing an error for each of them.
-        let definition_ty =
-            instantiated_ty.fold_with(&mut ReverseMapper::new(
-                self.tcx,
-                self.is_tainted_by_errors(),
-                def_id,
-                map,
-                instantiated_ty,
-            ));
-        debug!(
-            "infer_opaque_definition_from_instantiation: definition_ty={:?}",
-            definition_ty
-        );
+        let definition_ty = instantiated_ty.fold_with(&mut ReverseMapper::new(
+            self.tcx,
+            self.is_tainted_by_errors(),
+            def_id,
+            map,
+            instantiated_ty,
+        ));
+        debug!("infer_opaque_definition_from_instantiation: definition_ty={:?}", definition_ty);
 
         definition_ty
     }
 }
 
+pub fn unexpected_hidden_region_diagnostic(
+    tcx: TyCtxt<'tcx>,
+    region_scope_tree: Option<&region::ScopeTree>,
+    opaque_type_def_id: DefId,
+    hidden_ty: Ty<'tcx>,
+    hidden_region: ty::Region<'tcx>,
+) -> DiagnosticBuilder<'tcx> {
+    let span = tcx.def_span(opaque_type_def_id);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0700,
+        "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
+    );
+
+    // Explain the region we are capturing.
+    if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty = hidden_region {
+        // Assuming regionck succeeded (*), we ought to always be
+        // capturing *some* region from the fn header, and hence it
+        // ought to be free. So under normal circumstances, we will go
+        // down this path which gives a decent human readable
+        // explanation.
+        //
+        // (*) if not, the `tainted_by_errors` flag would be set to
+        // true in any case, so we wouldn't be here at all.
+        tcx.note_and_explain_free_region(
+            &mut err,
+            &format!("hidden type `{}` captures ", hidden_ty),
+            hidden_region,
+            "",
+        );
+    } else {
+        // Ugh. This is a painful case: the hidden region is not one
+        // that we can easily summarize or explain. This can happen
+        // in a case like
+        // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
+        //
+        // ```
+        // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
+        //   if condition() { a } else { b }
+        // }
+        // ```
+        //
+        // Here the captured lifetime is the intersection of `'a` and
+        // `'b`, which we can't quite express.
+
+        if let Some(region_scope_tree) = region_scope_tree {
+            // If the `region_scope_tree` is available, this is being
+            // invoked from the "region inferencer error". We can at
+            // least report a really cryptic error for now.
+            tcx.note_and_explain_region(
+                region_scope_tree,
+                &mut err,
+                &format!("hidden type `{}` captures ", hidden_ty),
+                hidden_region,
+                "",
+            );
+        } else {
+            // If the `region_scope_tree` is *unavailable*, this is
+            // being invoked by the code that comes *after* region
+            // inferencing. This is a bug, as the region inferencer
+            // ought to have noticed the failed constraint and invoked
+            // error reporting, which in turn should have prevented us
+            // from getting trying to infer the hidden type
+            // completely.
+            tcx.sess.delay_span_bug(
+                span,
+                &format!(
+                    "hidden type captures unexpected lifetime `{:?}` \
+                     but no region inference failure",
+                    hidden_region,
+                ),
+            );
+        }
+    }
+
+    err
+}
+
 // Visitor that requires that (almost) all regions in the type visited outlive
 // `least_region`. We cannot use `push_outlives_components` because regions in
 // closure signatures are not included in their outlives components. We need to
@@ -486,13 +683,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 //
 // We ignore any type parameters because impl trait values are assumed to
 // capture all the in-scope type parameters.
-struct OpaqueTypeOutlivesVisitor<'a, 'tcx> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    least_region: ty::Region<'tcx>,
-    span: Span,
+struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+    OP: FnMut(ty::Region<'tcx>),
+{
+    tcx: TyCtxt<'tcx>,
+    op: OP,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for OpaqueTypeOutlivesVisitor<'_, 'tcx> {
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+where
+    OP: FnMut(ty::Region<'tcx>),
+{
     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
         t.skip_binder().visit_with(self);
         false // keep visiting
@@ -503,7 +705,7 @@ impl<'tcx> TypeVisitor<'tcx> for OpaqueTypeOutlivesVisitor<'_, 'tcx> {
             // ignore bound regions, keep visiting
             ty::ReLateBound(_, _) => false,
             _ => {
-                self.infcx.sub_regions(infer::CallReturn(self.span), self.least_region, r);
+                (self.op)(r);
                 false
             }
         }
@@ -519,23 +721,23 @@ impl<'tcx> TypeVisitor<'tcx> for OpaqueTypeOutlivesVisitor<'_, 'tcx> {
             ty::Closure(def_id, ref substs) => {
                 // Skip lifetime parameters of the enclosing item(s)
 
-                for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
+                for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
                     upvar_ty.visit_with(self);
                 }
 
-                substs.closure_sig_ty(def_id, self.infcx.tcx).visit_with(self);
+                substs.closure_sig_ty(def_id, self.tcx).visit_with(self);
             }
 
             ty::Generator(def_id, ref substs, _) => {
                 // Skip lifetime parameters of the enclosing item(s)
                 // Also skip the witness type, because that has no free regions.
 
-                for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
+                for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
                     upvar_ty.visit_with(self);
                 }
 
-                substs.return_ty(def_id, self.infcx.tcx).visit_with(self);
-                substs.yield_ty(def_id, self.infcx.tcx).visit_with(self);
+                substs.return_ty(def_id, self.tcx).visit_with(self);
+                substs.yield_ty(def_id, self.tcx).visit_with(self);
             }
             _ => {
                 ty.super_visit_with(self);
@@ -616,40 +818,17 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
             None => {
                 if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
                     if let Some(hidden_ty) = self.hidden_ty.take() {
-                        let span = self.tcx.def_span(self.opaque_type_def_id);
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0700,
-                            "hidden type for `impl Trait` captures lifetime that \
-                             does not appear in bounds",
-                        );
-
-                        // Assuming regionck succeeded, then we must
-                        // be capturing *some* region from the fn
-                        // header, and hence it must be free, so it's
-                        // ok to invoke this fn (which doesn't accept
-                        // all regions, and would ICE if an
-                        // inappropriate region is given). We check
-                        // `is_tainted_by_errors` by errors above, so
-                        // we don't get in here unless regionck
-                        // succeeded. (Note also that if regionck
-                        // failed, then the regions we are attempting
-                        // to map here may well be giving errors
-                        // *because* the constraints were not
-                        // satisfiable.)
-                        self.tcx.note_and_explain_free_region(
-                            &mut err,
-                            &format!("hidden type `{}` captures ", hidden_ty),
+                        unexpected_hidden_region_diagnostic(
+                            self.tcx,
+                            None,
+                            self.opaque_type_def_id,
+                            hidden_ty,
                             r,
-                            ""
-                        );
-
-                        err.emit();
+                        ).emit();
                     }
                 }
                 self.tcx.lifetimes.re_empty
-            },
+            }
         }
     }
 
@@ -681,8 +860,8 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                 // during codegen.
 
                 let generics = self.tcx.generics_of(def_id);
-                let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
-                    |(index, &kind)| {
+                let substs =
+                    self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
                         if index < generics.parent_count {
                             // Accommodate missing regions in the parent kinds...
                             self.fold_kind_mapping_missing_regions_to_empty(kind)
@@ -690,16 +869,15 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                             // ...but not elsewhere.
                             self.fold_kind_normally(kind)
                         }
-                    },
-                ));
+                    }));
 
                 self.tcx.mk_closure(def_id, ty::ClosureSubsts { substs })
             }
 
             ty::Generator(def_id, substs, movability) => {
                 let generics = self.tcx.generics_of(def_id);
-                let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
-                    |(index, &kind)| {
+                let substs =
+                    self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
                         if index < generics.parent_count {
                             // Accommodate missing regions in the parent kinds...
                             self.fold_kind_mapping_missing_regions_to_empty(kind)
@@ -707,8 +885,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                             // ...but not elsewhere.
                             self.fold_kind_normally(kind)
                         }
-                    },
-                ));
+                    }));
 
                 self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability)
             }
@@ -723,6 +900,7 @@ struct Instantiator<'a, 'tcx> {
     parent_def_id: DefId,
     body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
+    value_span: Span,
     opaque_types: OpaqueTypeMap<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
 }
@@ -773,12 +951,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                         let parent_def_id = self.parent_def_id;
                         let def_scope_default = || {
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
-                            parent_def_id == tcx.hir()
-                                                .local_def_id_from_hir_id(opaque_parent_hir_id)
+                            parent_def_id
+                                == tcx.hir().local_def_id_from_hir_id(opaque_parent_hir_id)
                         };
-                        let (in_definition_scope, origin) =
-                            match tcx.hir().find(opaque_hir_id)
-                        {
+                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
                             Some(Node::Item(item)) => match item.node {
                                 // Anonymous `impl Trait`
                                 hir::ItemKind::Existential(hir::ExistTy {
@@ -847,10 +1023,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
         let infcx = self.infcx;
         let tcx = infcx.tcx;
 
-        debug!(
-            "instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})",
-            def_id, substs
-        );
+        debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
 
         // Use the same type variable if the exact same opaque type appears more
         // than once in the return type (e.g., if it's passed to a type alias).
@@ -858,41 +1031,35 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
             return opaque_defn.concrete_ty;
         }
         let span = tcx.def_span(def_id);
-        let ty_var = infcx.next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::TypeInference,
-            span,
-        });
+        let ty_var = infcx
+            .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
 
         let predicates_of = tcx.predicates_of(def_id);
-        debug!(
-            "instantiate_opaque_types: predicates={:#?}",
-            predicates_of,
-        );
+        debug!("instantiate_opaque_types: predicates={:#?}", predicates_of,);
         let bounds = predicates_of.instantiate(tcx, substs);
         debug!("instantiate_opaque_types: bounds={:?}", bounds);
 
         let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone());
-        debug!(
-            "instantiate_opaque_types: required_region_bounds={:?}",
-            required_region_bounds
-        );
+        debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
 
         // Make sure that we are in fact defining the *entire* type
         // (e.g., `existential type Foo<T: Bound>: Bar;` needs to be
         // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
-        debug!(
-            "instantiate_opaque_types: param_env={:#?}",
-            self.param_env,
-        );
-        debug!(
-            "instantiate_opaque_types: generics={:#?}",
-            tcx.generics_of(def_id),
-        );
+        debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
+        debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
+
+        // Ideally, we'd get the span where *this specific `ty` came
+        // from*, but right now we just use the span from the overall
+        // value being folded. In simple cases like `-> impl Foo`,
+        // these are the same span, but not in cases like `-> (impl
+        // Foo, impl Bar)`.
+        let definition_span = self.value_span;
 
         self.opaque_types.insert(
             def_id,
             OpaqueTypeDecl {
                 substs,
+                definition_span,
                 concrete_ty: ty_var,
                 has_required_region_bounds: !required_region_bounds.is_empty(),
                 origin,
@@ -911,8 +1078,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
 
             // Require that the predicate holds for the concrete type.
             debug!("instantiate_opaque_types: predicate={:?}", predicate);
-            self.obligations
-                .push(traits::Obligation::new(cause, self.param_env, predicate));
+            self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
         }
 
         ty_var
@@ -950,9 +1116,7 @@ pub fn may_define_existential_type(
     );
 
     // Named existential types can be defined by any siblings or children of siblings.
-    let scope = tcx.hir()
-        .get_defining_scope(opaque_hir_id)
-        .expect("could not get defining scope");
+    let scope = tcx.hir().get_defining_scope(opaque_hir_id).expect("could not get defining scope");
     // We walk up the node tree until we hit the root or the scope of the opaque type.
     while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
         hir_id = tcx.hir().get_parent_item(hir_id);
diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs
index 1250995a59c..c085df6a6e7 100644
--- a/src/librustc/infer/outlives/free_region_map.rs
+++ b/src/librustc/infer/outlives/free_region_map.rs
@@ -11,6 +11,10 @@ pub struct FreeRegionMap<'tcx> {
 }
 
 impl<'tcx> FreeRegionMap<'tcx> {
+    pub fn elements(&self) -> impl Iterator<Item=&Region<'tcx>> {
+        self.relation.elements()
+    }
+
     pub fn is_empty(&self) -> bool {
         self.relation.is_empty()
     }
diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs
index 0ae4446ee63..e1470e4ef02 100644
--- a/src/librustc/infer/outlives/obligations.rs
+++ b/src/librustc/infer/outlives/obligations.rs
@@ -112,7 +112,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 
     /// Trait queries just want to pass back type obligations "as is"
     pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> {
-        ::std::mem::replace(&mut *self.region_obligations.borrow_mut(), vec![])
+        ::std::mem::take(&mut *self.region_obligations.borrow_mut())
     }
 
     /// Process the region obligations that must be proven (during
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index f2235fe8d6d..21904edb309 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -8,11 +8,14 @@ use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unify as ut;
+use crate::hir::def_id::DefId;
 use crate::ty::ReStatic;
 use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::{ReLateBound, ReVar};
 use crate::ty::{Region, RegionVid};
+use syntax_pos::Span;
 
 use std::collections::BTreeMap;
 use std::{cmp, fmt, mem};
@@ -78,6 +81,11 @@ pub struct RegionConstraintData<'tcx> {
     /// be a region variable (or neither, as it happens).
     pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
 
+    /// Constraints of the form `R0 member of [R1, ..., Rn]`, meaning that
+    /// `R0` must be equal to one of the regions `R1..Rn`. These occur
+    /// with `impl Trait` quite frequently.
+    pub member_constraints: Vec<MemberConstraint<'tcx>>,
+
     /// A "verify" is something that we need to verify after inference
     /// is done, but which does not directly affect inference in any
     /// way.
@@ -137,6 +145,43 @@ impl Constraint<'_> {
     }
 }
 
+/// Requires that `region` must be equal to one of the regions in `choice_regions`.
+/// We often denote this using the syntax:
+///
+/// ```
+/// R0 member of [O1..On]
+/// ```
+#[derive(Debug, Clone, HashStable)]
+pub struct MemberConstraint<'tcx> {
+    /// The `DefId` of the opaque type causing this constraint: used for error reporting.
+    pub opaque_type_def_id: DefId,
+
+    /// The span where the hidden type was instantiated.
+    pub definition_span: Span,
+
+    /// The hidden type in which `member_region` appears: used for error reporting.
+    pub hidden_ty: Ty<'tcx>,
+
+    /// The region `R0`.
+    pub member_region: Region<'tcx>,
+
+    /// The options `O1..On`.
+    pub choice_regions: Lrc<Vec<Region<'tcx>>>,
+}
+
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for MemberConstraint<'tcx> {
+        opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for MemberConstraint<'a> {
+        type Lifted = MemberConstraint<'tcx>;
+        opaque_type_def_id, definition_span, hidden_ty, member_region, choice_regions
+    }
+}
+
 /// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
 /// associated type) must outlive the region `R`. `T` is known to
 /// outlive `RS`. Therefore, verify that `R <= RS[i]` for some
@@ -410,7 +455,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
             *any_unifications = false;
         }
 
-        mem::replace(data, RegionConstraintData::default())
+        mem::take(data)
     }
 
     pub fn data(&self) -> &RegionConstraintData<'tcx> {
@@ -643,6 +688,30 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
     }
 
+    pub fn member_constraint(
+        &mut self,
+        opaque_type_def_id: DefId,
+        definition_span: Span,
+        hidden_ty: Ty<'tcx>,
+        member_region: ty::Region<'tcx>,
+        choice_regions: &Lrc<Vec<ty::Region<'tcx>>>,
+    ) {
+        debug!("member_constraint({:?} in {:#?})", member_region, choice_regions);
+
+        if choice_regions.iter().any(|&r| r == member_region) {
+            return;
+        }
+
+        self.data.member_constraints.push(MemberConstraint {
+            opaque_type_def_id,
+            definition_span,
+            hidden_ty,
+            member_region,
+            choice_regions: choice_regions.clone()
+        });
+
+    }
+
     pub fn make_subregion(
         &mut self,
         origin: SubregionOrigin<'tcx>,
@@ -906,9 +975,13 @@ impl<'tcx> RegionConstraintData<'tcx> {
     pub fn is_empty(&self) -> bool {
         let RegionConstraintData {
             constraints,
+            member_constraints,
             verifys,
             givens,
         } = self;
-        constraints.is_empty() && verifys.is_empty() && givens.is_empty()
+        constraints.is_empty() &&
+            member_constraints.is_empty() &&
+            verifys.is_empty() &&
+            givens.is_empty()
     }
 }
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index dcafb0f3976..e30e86998a8 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -115,7 +115,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
     ///
     /// Note that this function does not return care whether
     /// `vid` has been unified with something else or not.
-    pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
+    pub fn var_diverges(&self, vid: ty::TyVid) -> bool {
         self.values.get(vid.index as usize).diverging
     }
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 257d5159f11..c4c23428002 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -35,6 +35,8 @@
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_fn)]
+#![feature(const_transmute)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(inner_deref)]
@@ -65,6 +67,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(proc_macro_hygiene)]
 #![feature(log_syntax)]
+#![feature(mem_take)]
 
 #![recursion_limit="512"]
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 309af4b72c1..59b08b832d2 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -765,7 +765,7 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
     attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some())
 }
 
-fn lint_levels<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx LintLevelMap {
+fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
     assert_eq!(cnum, LOCAL_CRATE);
     let mut builder = LintLevelMapBuilder {
         levels: LintLevelSets::builder(tcx.sess),
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 2e9e1ac582f..5a580dfa420 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -211,7 +211,7 @@ pub trait CrateStore {
     fn crates_untracked(&self) -> Vec<CrateNum>;
 
     // utility functions
-    fn encode_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>) -> EncodedMetadata;
+    fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata;
     fn metadata_encoding_version(&self) -> &[u8];
 }
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index e02ee894360..e1889aa555f 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -26,7 +26,7 @@ use syntax_pos;
 // explored. For example, if it's a live Node::Item that is a
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
-fn should_explore<'tcx>(tcx: TyCtxt<'tcx>, hir_id: hir::HirId) -> bool {
+fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
     match tcx.hir().find(hir_id) {
         Some(Node::Item(..)) |
         Some(Node::ImplItem(..)) |
@@ -662,7 +662,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
     }
 }
 
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
     let krate = tcx.hir().krate();
     let live_symbols = find_live(tcx, access_levels, krate);
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 879da6413e2..96b99fe4cdc 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -81,7 +81,7 @@ pub enum Linkage {
     Dynamic,
 }
 
-pub fn calculate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn calculate(tcx: TyCtxt<'_>) {
     let sess = &tcx.sess;
     let fmts = sess.crate_types.borrow().iter().map(|&ty| {
         let linkage = calculate_type(tcx, ty);
@@ -92,7 +92,7 @@ pub fn calculate<'tcx>(tcx: TyCtxt<'tcx>) {
     sess.dependency_formats.set(fmts);
 }
 
-fn calculate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: config::CrateType) -> DependencyList {
+fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList {
     let sess = &tcx.sess;
 
     if !sess.opts.output_types.should_codegen() {
@@ -267,7 +267,7 @@ fn add_library(
     }
 }
 
-fn attempt_static<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DependencyList> {
+fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
     let sess = &tcx.sess;
     let crates = cstore::used_crates(tcx, RequireStatic);
     if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
@@ -324,7 +324,7 @@ fn activate_injected_dep(injected: Option<CrateNum>,
 
 // After the linkage for a crate has been determined we need to verify that
 // there's only going to be one allocator in the output.
-fn verify_ok<'tcx>(tcx: TyCtxt<'tcx>, list: &[Linkage]) {
+fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
     let sess = &tcx.sess;
     if list.len() == 0 {
         return
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 086ddfd7e33..c93cc847adf 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -11,6 +11,7 @@ use self::OverloadedCallType::*;
 
 use crate::hir::def::{CtorOf, Res, DefKind};
 use crate::hir::def_id::DefId;
+use crate::hir::ptr::P;
 use crate::infer::InferCtxt;
 use crate::middle::mem_categorization as mc;
 use crate::middle::region;
@@ -18,7 +19,6 @@ use crate::ty::{self, DefIdTree, TyCtxt, adjustment};
 
 use crate::hir::{self, PatKind};
 use std::rc::Rc;
-use syntax::ptr::P;
 use syntax_pos::Span;
 use crate::util::nodemap::ItemLocalSet;
 
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index e8d68e0b7a7..1cc96c549e7 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -10,7 +10,7 @@ use syntax_pos::{Span, sym};
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::hir;
 
-fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
         &mut ItemVisitor { tcx }.as_deep_visitor()
diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs
index 9c131ce6342..694b0a98629 100644
--- a/src/librustc/middle/lib_features.rs
+++ b/src/librustc/middle/lib_features.rs
@@ -142,7 +142,7 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
     }
 }
 
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LibFeatures {
+pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
     intravisit::walk_crate(&mut collector, tcx.hir().krate());
     collector.lib_features
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 7b69fe394fb..30ff835bdcc 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -99,6 +99,7 @@ use self::VarKind::*;
 
 use crate::hir::def::*;
 use crate::hir::Node;
+use crate::hir::ptr::P;
 use crate::ty::{self, TyCtxt};
 use crate::ty::query::Providers;
 use crate::lint;
@@ -111,7 +112,6 @@ use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ptr::P;
 use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 
@@ -181,7 +181,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
 }
 
-fn check_mod_liveness<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
         &mut IrMaps::new(tcx, module_def_id).as_deep_visitor(),
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index e7253a73bd4..088c862dcb8 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -465,9 +465,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
     ) -> bool {
         self.infcx.map(|infcx| infcx.type_is_copy_modulo_regions(param_env, ty, span))
             .or_else(|| {
-                self.tcx.lift_to_global(&(param_env, ty)).map(|(param_env, ty)| {
-                    ty.is_copy_modulo_regions(self.tcx.global_tcx(), param_env, span)
-                })
+                if (param_env, ty).has_local_value() {
+                    None
+                } else {
+                    Some(ty.is_copy_modulo_regions(self.tcx, param_env, span))
+                }
             })
             .unwrap_or(true)
     }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index d607c35f876..6b26be34d75 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -42,8 +42,8 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAt
     }
 }
 
-fn method_might_be_inlined<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn method_might_be_inlined(
+    tcx: TyCtxt<'_>,
     impl_item: &hir::ImplItem,
     impl_src: DefId,
 ) -> bool {
@@ -391,7 +391,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
 #[derive(Clone, HashStable)]
 pub struct ReachableSet(pub Lrc<HirIdSet>);
 
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> ReachableSet {
+fn reachable_set(tcx: TyCtxt<'_>, crate_num: CrateNum) -> ReachableSet {
     debug_assert!(crate_num == LOCAL_CRATE);
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 114684b1524..f859e835425 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -1375,7 +1375,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
 
         let outer_ec = mem::replace(&mut self.expr_and_pat_count, 0);
         let outer_cx = self.cx;
-        let outer_ts = mem::replace(&mut self.terminating_scopes, FxHashSet::default());
+        let outer_ts = mem::take(&mut self.terminating_scopes);
         self.terminating_scopes.insert(body.value.hir_id.local_id);
 
         if let Some(root_id) = self.cx.root_id {
@@ -1446,7 +1446,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
     }
 }
 
-fn region_scope_tree<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ScopeTree {
+fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
     let closure_base_def_id = tcx.closure_base_def_id(def_id);
     if closure_base_def_id != def_id {
         return tcx.region_scope_tree(closure_base_def_id);
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 412346bab25..758f14ebf99 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -8,6 +8,7 @@
 use crate::hir::def::{Res, DefKind};
 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use crate::hir::map::Map;
+use crate::hir::ptr::P;
 use crate::hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, Node, ParamName};
 use crate::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
 
@@ -18,10 +19,9 @@ use errors::{Applicability, DiagnosticBuilder};
 use rustc_macros::HashStable;
 use std::borrow::Cow;
 use std::cell::Cell;
-use std::mem::replace;
+use std::mem::{replace, take};
 use syntax::ast;
 use syntax::attr;
-use syntax::ptr::P;
 use syntax::symbol::{kw, sym};
 use syntax_pos::Span;
 
@@ -368,7 +368,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
 /// entire crate. You should not read the result of this query
 /// directly, but rather use `named_region_map`, `is_late_bound_map`,
 /// etc.
-fn resolve_lifetimes<'tcx>(tcx: TyCtxt<'tcx>, for_krate: CrateNum) -> &'tcx ResolveLifetimes {
+fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes {
     assert_eq!(for_krate, LOCAL_CRATE);
 
     let named_region_map = krate(tcx);
@@ -395,7 +395,7 @@ fn resolve_lifetimes<'tcx>(tcx: TyCtxt<'tcx>, for_krate: CrateNum) -> &'tcx Reso
     tcx.arena.alloc(rl)
 }
 
-fn krate<'tcx>(tcx: TyCtxt<'tcx>) -> NamedRegionMap {
+fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
     let krate = tcx.hir().krate();
     let mut map = NamedRegionMap {
         defs: Default::default(),
@@ -441,7 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
 
     fn visit_nested_body(&mut self, body: hir::BodyId) {
         // Each body has their own set of labels, save labels.
-        let saved = replace(&mut self.labels_in_fn, vec![]);
+        let saved = take(&mut self.labels_in_fn);
         let body = self.tcx.hir().body(body);
         extract_labels(self, body);
         self.with(
@@ -1405,9 +1405,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             lifetime_uses,
             ..
         } = self;
-        let labels_in_fn = replace(&mut self.labels_in_fn, vec![]);
-        let xcrate_object_lifetime_defaults =
-            replace(&mut self.xcrate_object_lifetime_defaults, DefIdMap::default());
+        let labels_in_fn = take(&mut self.labels_in_fn);
+        let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
         let mut this = LifetimeContext {
             tcx: *tcx,
             map: map,
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 38df4060652..101563d2d99 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -466,7 +466,7 @@ impl<'tcx> Index<'tcx> {
 
 /// Cross-references the feature names of unstable APIs with enabled
 /// features and possibly prints errors.
-fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }.as_deep_visitor());
 }
 
@@ -836,7 +836,7 @@ impl<'tcx> TyCtxt<'tcx> {
 /// Given the list of enabled features that were not language features (i.e., that
 /// were expected to be library features), and the list of features used from
 /// libraries, identify activated features that don't exist and error about them.
-pub fn check_unused_or_stable_features<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
     if tcx.stability().staged_api[&LOCAL_CRATE] {
@@ -920,8 +920,8 @@ pub fn check_unused_or_stable_features<'tcx>(tcx: TyCtxt<'tcx>) {
     // don't lint about unused features. We should reenable this one day!
 }
 
-fn unnecessary_stable_feature_lint<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn unnecessary_stable_feature_lint(
+    tcx: TyCtxt<'_>,
     span: Span,
     feature: Symbol,
     since: Symbol,
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index e8113b4516c..c8f42b1c604 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -18,7 +18,7 @@ use errors::DiagnosticBuilder;
 use syntax_pos::{Pos, Span};
 use syntax::symbol::Symbol;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
     /// Already reported a lint or an error for this evaluation.
     Reported,
@@ -37,6 +37,10 @@ impl ErrorHandled {
     }
 }
 
+CloneTypeFoldableImpls! {
+    ErrorHandled,
+}
+
 pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
 pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
 
@@ -178,7 +182,7 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
 /// up with a Rust-level backtrace of where the error occured.
 /// Thsese should always be constructed by calling `.into()` on
 /// a `InterpError`. In `librustc_mir::interpret`, we have the `err!`
-/// macro for this
+/// macro for this.
 #[derive(Debug, Clone)]
 pub struct InterpErrorInfo<'tcx> {
     pub kind: InterpError<'tcx, u64>,
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 9b1808c585c..59a032d53cf 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2867,19 +2867,19 @@ impl<'tcx> graph::WithStartNode for Body<'tcx> {
 }
 
 impl<'tcx> graph::WithPredecessors for Body<'tcx> {
-    fn predecessors<'graph>(
-        &'graph self,
+    fn predecessors(
+        &self,
         node: Self::Node,
-    ) -> <Self as GraphPredecessors<'graph>>::Iter {
+    ) -> <Self as GraphPredecessors<'_>>::Iter {
         self.predecessors_for(node).clone().into_iter()
     }
 }
 
 impl<'tcx> graph::WithSuccessors for Body<'tcx> {
-    fn successors<'graph>(
-        &'graph self,
+    fn successors(
+        &self,
         node: Self::Node,
-    ) -> <Self as GraphSuccessors<'graph>>::Iter {
+    ) -> <Self as GraphSuccessors<'_>>::Iter {
         self.basic_blocks[node].terminator().successors().cloned()
     }
 }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 10efef54526..d2082ab87e7 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -2,7 +2,7 @@ use crate::ty::query::QueryDescription;
 use crate::ty::query::queries;
 use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use crate::ty::subst::SubstsRef;
-use crate::dep_graph::SerializedDepNodeIndex;
+use crate::dep_graph::{RecoverKey,DepKind, DepNode, SerializedDepNodeIndex};
 use crate::hir::def_id::{CrateNum, DefId, DefIndex};
 use crate::mir;
 use crate::mir::interpret::GlobalId;
@@ -33,13 +33,13 @@ rustc_queries! {
     Other {
         /// Records the type of every item.
         query type_of(key: DefId) -> Ty<'tcx> {
-            cache { key.is_local() }
+            cache_on_disk_if { key.is_local() }
         }
 
         /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
         /// associated generics.
         query generics_of(key: DefId) -> &'tcx ty::Generics {
-            cache { key.is_local() }
+            cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
                 let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
                                                         .try_load_query_result(tcx, id);
@@ -62,7 +62,9 @@ rustc_queries! {
         /// predicate gets in the way of some checks, which are intended
         /// to operate over only the actual where-clauses written by the
         /// user.)
-        query predicates_of(_: DefId) -> &'tcx ty::GenericPredicates<'tcx> {}
+        query predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
+            cache_on_disk_if { key.is_local() }
+        }
 
         query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
             desc { "looking up the native libraries of a linked crate" }
@@ -93,7 +95,7 @@ rustc_queries! {
         /// of the MIR qualify_consts pass. The actual meaning of
         /// the value isn't known except to the pass itself.
         query mir_const_qualif(key: DefId) -> (u8, &'tcx BitSet<mir::Local>) {
-            cache { key.is_local() }
+            cache_on_disk_if { key.is_local() }
         }
 
         /// Fetch the MIR for a given `DefId` right after it's built - this includes
@@ -115,7 +117,7 @@ rustc_queries! {
         /// MIR after our optimization passes have run. This is MIR that is ready
         /// for codegen. This is also the only query that can fetch non-local MIR, at present.
         query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
-            cache { key.is_local() }
+            cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
                 let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
                                                             .try_load_query_result(tcx, id);
@@ -285,7 +287,9 @@ rustc_queries! {
 
     TypeChecking {
         /// The result of unsafety-checking this `DefId`.
-        query unsafety_check_result(_: DefId) -> mir::UnsafetyCheckResult {}
+        query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult {
+            cache_on_disk_if { key.is_local() }
+        }
 
         /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
         query unsafe_derive_on_repr_packed(_: DefId) -> () {}
@@ -348,7 +352,7 @@ rustc_queries! {
         }
 
         query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
-            cache { key.is_local() }
+            cache_on_disk_if { key.is_local() }
             load_cached(tcx, id) {
                 let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
                     .queries.on_disk_cache
@@ -360,7 +364,9 @@ rustc_queries! {
     }
 
     Other {
-        query used_trait_imports(_: DefId) -> &'tcx DefIdSet {}
+        query used_trait_imports(key: DefId) -> &'tcx DefIdSet {
+            cache_on_disk_if { key.is_local() }
+        }
     }
 
     TypeChecking {
@@ -372,11 +378,15 @@ rustc_queries! {
     }
 
     BorrowChecking {
-        query borrowck(_: DefId) -> &'tcx BorrowCheckResult {}
+        query borrowck(key: DefId) -> &'tcx BorrowCheckResult {
+            cache_on_disk_if { key.is_local() }
+        }
 
         /// 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> {}
+        query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> {
+            cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) }
+        }
     }
 
     TypeChecking {
@@ -412,9 +422,10 @@ rustc_queries! {
                 "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)
+            cache_on_disk_if(_, opt_result) {
+                // Only store results without errors
+                // FIXME: We never store these
+                opt_result.map_or(true, |r| r.is_ok())
             }
         }
 
@@ -427,9 +438,9 @@ rustc_queries! {
                 "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)
+            cache_on_disk_if(_, opt_result) {
+                // Only store results without errors
+                opt_result.map_or(true, |r| r.is_ok())
             }
         }
 
@@ -453,7 +464,9 @@ rustc_queries! {
     }
 
     TypeChecking {
-        query check_match(_: DefId) -> () {}
+        query check_match(key: DefId) -> () {
+            cache_on_disk_if { key.is_local() }
+        }
 
         /// Performs part of the privacy check and computes "access levels".
         query privacy_access_levels(_: CrateNum) -> &'tcx AccessLevels {
@@ -483,7 +496,7 @@ rustc_queries! {
         query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
             no_force
             desc { "computing the symbol for `{}`", key }
-            cache { true }
+            cache_on_disk_if { true }
         }
 
         query def_kind(_: DefId) -> Option<DefKind> {}
@@ -501,7 +514,9 @@ rustc_queries! {
     }
 
     Codegen {
-        query codegen_fn_attrs(_: DefId) -> CodegenFnAttrs {}
+        query codegen_fn_attrs(_: DefId) -> CodegenFnAttrs {
+            cache_on_disk_if { true }
+        }
     }
 
     Other {
@@ -519,7 +534,7 @@ rustc_queries! {
                 "const checking if rvalue is promotable to static `{}`",
                 tcx.def_path_str(key)
             }
-            cache { true }
+            cache_on_disk_if { true }
         }
         query rvalue_promotable_map(key: DefId) -> &'tcx ItemLocalSet {
             desc { |tcx|
@@ -548,7 +563,7 @@ rustc_queries! {
             key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
         ) -> Vtable<'tcx, ()> {
             no_force
-            cache { true }
+            cache_on_disk_if { true }
             desc { |tcx|
                 "checking if `{}` fulfills its obligations",
                 tcx.def_path_str(key.1.def_id())
@@ -560,7 +575,9 @@ rustc_queries! {
         query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls {
             desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) }
         }
-        query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {}
+        query specialization_graph_of(_: DefId) -> &'tcx specialization_graph::Graph {
+            cache_on_disk_if { true }
+        }
         query is_object_safe(key: DefId) -> bool {
             desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) }
         }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 895f9c6d8fb..82c53be3ec7 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -269,11 +269,11 @@ impl OutputTypes {
         self.0.contains_key(key)
     }
 
-    pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
+    pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> {
         self.0.keys()
     }
 
-    pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
+    pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> {
         self.0.values()
     }
 
@@ -316,7 +316,7 @@ impl Externs {
         self.0.get(key)
     }
 
-    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, ExternEntry> {
+    pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
         self.0.iter()
     }
 }
@@ -1207,7 +1207,11 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
     linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
         parse_linker_plugin_lto, [TRACKED],
         "generate build artifacts that are compatible with linker-based LTO."),
-
+    profile_generate: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
+        parse_switch_with_opt_path, [TRACKED],
+        "compile the program with profiling instrumentation"),
+    profile_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+        "use the given `.profdata` file for profile-guided optimization"),
 }
 
 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
@@ -1379,11 +1383,6 @@ 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: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
-        parse_switch_with_opt_path, [TRACKED],
-        "Generate PGO profile data, to a given file, or to the default location if it's empty."),
-    pgo_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
-        "Use PGO profile data from the given profile file."),
     disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED],
         "Disable the instrumentation pre-inliner, useful for profiling / PGO."),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
@@ -2036,13 +2035,6 @@ pub fn build_session_options_and_crate_config(
         }
     }
 
-    if debugging_opts.pgo_gen.enabled() && debugging_opts.pgo_use.is_some() {
-        early_error(
-            error_format,
-            "options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
-        );
-    }
-
     let mut output_types = BTreeMap::new();
     if !debugging_opts.parse_only {
         for list in matches.opt_strs("emit") {
@@ -2154,6 +2146,13 @@ pub fn build_session_options_and_crate_config(
         );
     }
 
+    if cg.profile_generate.enabled() && cg.profile_use.is_some() {
+        early_error(
+            error_format,
+            "options `-C profile-generate` and `-C profile-use` are exclusive",
+        );
+    }
+
     let mut prints = Vec::<PrintRequest>::new();
     if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
         prints.push(PrintRequest::TargetCPUs);
diff --git a/src/librustc/session/config/tests.rs b/src/librustc/session/config/tests.rs
index b8477f8dd17..3d6312548a4 100644
--- a/src/librustc/session/config/tests.rs
+++ b/src/librustc/session/config/tests.rs
@@ -519,11 +519,11 @@ fn test_codegen_options_tracking_hash() {
     assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
     opts = reference.clone();
-    opts.debugging_opts.pgo_gen = SwitchWithOptPath::Enabled(None);
+    opts.cg.profile_generate = SwitchWithOptPath::Enabled(None);
     assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
     opts = reference.clone();
-    opts.debugging_opts.pgo_use = Some(PathBuf::from("abc"));
+    opts.cg.profile_use = Some(PathBuf::from("abc"));
     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 bb4ef2d7bd4..3cbf0ee213a 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -215,66 +215,66 @@ impl Session {
         *self.crate_disambiguator.get()
     }
 
-    pub fn struct_span_warn<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_warn<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_warn(sp, msg)
     }
-    pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
-    pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_warn(msg)
     }
-    pub fn struct_span_err<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_err<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_err(sp, msg)
     }
-    pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
     // FIXME: This method should be removed (every error should have an associated error code).
-    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_err(msg)
     }
-    pub fn struct_err_with_code<'a>(
-        &'a self,
+    pub fn struct_err_with_code(
+        &self,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_err_with_code(msg, code)
     }
-    pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_fatal<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
-    pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(
-        &'a self,
+    pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
+        &self,
         sp: S,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
-    pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
         self.diagnostic().struct_fatal(msg)
     }
 
@@ -416,7 +416,7 @@ impl Session {
     pub fn next_node_id(&self) -> NodeId {
         self.reserve_node_ids(1)
     }
-    pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler {
+    pub fn diagnostic(&self) -> &errors::Handler {
         &self.parse_sess.span_diagnostic
     }
 
@@ -504,7 +504,7 @@ impl Session {
         );
     }
 
-    pub fn source_map<'a>(&'a self) -> &'a source_map::SourceMap {
+    pub fn source_map(&self) -> &source_map::SourceMap {
         self.parse_sess.source_map()
     }
     pub fn verbose(&self) -> bool {
@@ -1295,9 +1295,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
 
     // Make sure that any given profiling data actually exists so LLVM can't
     // decide to silently skip PGO.
-    if let Some(ref path) = sess.opts.debugging_opts.pgo_use {
+    if let Some(ref path) = sess.opts.cg.profile_use {
         if !path.exists() {
-            sess.err(&format!("File `{}` passed to `-Zpgo-use` does not exist.",
+            sess.err(&format!("File `{}` passed to `-C profile-use` does not exist.",
                               path.display()));
         }
     }
@@ -1306,7 +1306,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     // an error to combine the two for now. It always runs into an assertions
     // if LLVM is built with assertions, but without assertions it sometimes
     // does not crash and will probably generate a corrupted binary.
-    if sess.opts.debugging_opts.pgo_gen.enabled() &&
+    if sess.opts.cg.profile_generate.enabled() &&
        sess.target.target.options.is_like_msvc &&
        sess.panic_strategy() == PanicStrategy::Unwind {
         sess.err("Profile-guided optimization does not yet work in conjunction \
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index d8087af60ac..b6f0addd771 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -48,8 +48,8 @@ pub fn add_placeholder_note(err: &mut errors::DiagnosticBuilder<'_>) {
 /// If there are types that satisfy both impls, invokes `on_overlap`
 /// with a suitably-freshened `ImplHeader` with those types
 /// substituted. Otherwise, invokes `no_overlap`.
-pub fn overlapping_impls<'tcx, F1, F2, R>(
-    tcx: TyCtxt<'tcx>,
+pub fn overlapping_impls<F1, F2, R>(
+    tcx: TyCtxt<'_>,
     impl1_def_id: DefId,
     impl2_def_id: DefId,
     intercrate_mode: IntercrateMode,
@@ -247,10 +247,10 @@ pub enum OrphanCheckErr<'tcx> {
 ///
 /// 1. All type parameters in `Self` must be "covered" by some local type constructor.
 /// 2. Some local type must appear in `Self`.
-pub fn orphan_check<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn orphan_check(
+    tcx: TyCtxt<'_>,
     impl_def_id: DefId,
-) -> Result<(), OrphanCheckErr<'tcx>> {
+) -> Result<(), OrphanCheckErr<'_>> {
     debug!("orphan_check({:?})", impl_def_id);
 
     // We only except this routine to be invoked on implementations
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index f54575ff8fc..d6cc68bcdab 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -247,7 +247,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         /// returns the fuzzy category of a given type, or None
         /// if the type can be equated to any type.
-        fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
+        fn type_category(t: Ty<'_>) -> Option<u32> {
             match t.sty {
                 ty::Bool => Some(0),
                 ty::Char => Some(1),
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index f106458c767..99b5ef3894b 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -461,41 +461,35 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
             }
 
             ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.selcx.tcx().lift_to_global(&obligation.param_env) {
-                    None => {
+                if obligation.param_env.has_local_value() {
                         ProcessResult::Unchanged
-                    }
-                    Some(param_env) => {
-                        match self.selcx.tcx().lift_to_global(&substs) {
-                            Some(substs) => {
-                                let instance = ty::Instance::resolve(
-                                    self.selcx.tcx().global_tcx(),
-                                    param_env,
-                                    def_id,
-                                    substs,
-                                );
-                                if let Some(instance) = instance {
-                                    let cid = GlobalId {
-                                        instance,
-                                        promoted: None,
-                                    };
-                                    match self.selcx.tcx().at(obligation.cause.span)
-                                                          .const_eval(param_env.and(cid)) {
-                                        Ok(_) => ProcessResult::Changed(vec![]),
-                                        Err(err) => ProcessResult::Error(
-                                            CodeSelectionError(ConstEvalFailure(err)))
-                                    }
-                                } else {
-                                    ProcessResult::Error(CodeSelectionError(
-                                        ConstEvalFailure(ErrorHandled::TooGeneric)
-                                    ))
-                                }
-                            },
-                            None => {
-                                pending_obligation.stalled_on = substs.types().collect();
-                                ProcessResult::Unchanged
+                } else {
+                    if !substs.has_local_value() {
+                        let instance = ty::Instance::resolve(
+                            self.selcx.tcx().global_tcx(),
+                            obligation.param_env,
+                            def_id,
+                            substs,
+                        );
+                        if let Some(instance) = instance {
+                            let cid = GlobalId {
+                                instance,
+                                promoted: None,
+                            };
+                            match self.selcx.tcx().at(obligation.cause.span)
+                                                    .const_eval(obligation.param_env.and(cid)) {
+                                Ok(_) => ProcessResult::Changed(vec![]),
+                                Err(err) => ProcessResult::Error(
+                                    CodeSelectionError(ConstEvalFailure(err)))
                             }
+                        } else {
+                            ProcessResult::Error(CodeSelectionError(
+                                ConstEvalFailure(ErrorHandled::TooGeneric)
+                            ))
                         }
+                    } else {
+                        pending_obligation.stalled_on = substs.types().collect();
+                        ProcessResult::Unchanged
                     }
                 }
             }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 8d17df1e610..1ca92d79fa5 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -457,6 +457,16 @@ pub enum SelectionError<'tcx> {
     Overflow,
 }
 
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for SelectionError<'tcx> {
+        (SelectionError::Unimplemented),
+        (SelectionError::OutputTypeParameterMismatch)(a, b, c),
+        (SelectionError::TraitNotObjectSafe)(a),
+        (SelectionError::ConstEvalFailure)(a),
+        (SelectionError::Overflow),
+    }
+}
+
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>
@@ -782,13 +792,11 @@ fn do_normalize_predicates<'tcx>(
                 return Err(ErrorReported)
             }
         };
-
-        match tcx.lift_to_global(&predicates) {
-            Some(predicates) => Ok(predicates),
-            None => {
-                // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
-                Err(ErrorReported)
-            }
+        if predicates.has_local_value() {
+            // FIXME: shouldn't we, you know, actually report an error here? or an ICE?
+            Err(ErrorReported)
+        } else {
+            Ok(predicates)
         }
     })
 }
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index cfd5cfa897d..37eff852abd 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -702,6 +702,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 }
 
-pub(super) fn is_object_safe_provider<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> bool {
+pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
     tcx.object_safety_violations(trait_def_id).is_empty()
 }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 0f4b7aff82b..20acf443406 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -399,7 +399,8 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
     fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
-            if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
+            let param_env = self.param_env;
+            if !param_env.has_local_value() {
                 if substs.needs_infer() || substs.has_placeholders() {
                     let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
@@ -414,7 +415,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                         }
                     }
                 } else {
-                    if let Some(substs) = self.tcx().lift_to_global(&substs) {
+                    if !substs.has_local_value() {
                         let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
                         if let Some(instance) = instance {
                             let cid = GlobalId {
@@ -1508,8 +1509,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
 ///
 /// Based on the "projection mode", this lookup may in fact only examine the
 /// topmost impl. See the comments for `Reveal` for more details.
-fn assoc_ty_def<'cx, 'tcx>(
-    selcx: &SelectionContext<'cx, 'tcx>,
+fn assoc_ty_def(
+    selcx: &SelectionContext<'_, '_>,
     impl_def_id: DefId,
     assoc_ty_def_id: DefId,
 ) -> specialization_graph::NodeItem<ty::AssocItem> {
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 5dd1b9e3d53..55e622e46b9 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -193,7 +193,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
     fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
-            if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
+            let param_env = self.param_env;
+            if !param_env.has_local_value() {
                 if substs.needs_infer() || substs.has_placeholders() {
                     let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
@@ -208,7 +209,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                         }
                     }
                 } else {
-                    if let Some(substs) = self.tcx().lift_to_global(&substs) {
+                    if !substs.has_local_value() {
                         let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
                         if let Some(instance) = instance {
                             let cid = GlobalId {
diff --git a/src/librustc/traits/query/type_op/custom.rs b/src/librustc/traits/query/type_op/custom.rs
index 72550e23460..a2a5f3f950c 100644
--- a/src/librustc/traits/query/type_op/custom.rs
+++ b/src/librustc/traits/query/type_op/custom.rs
@@ -3,7 +3,7 @@ use std::fmt;
 use crate::traits::query::Fallible;
 
 use crate::infer::canonical::query_response;
-use crate::infer::canonical::QueryRegionConstraint;
+use crate::infer::canonical::QueryRegionConstraints;
 use std::rc::Rc;
 use syntax::source_map::DUMMY_SP;
 use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
@@ -39,7 +39,7 @@ where
     fn fully_perform(
         self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
         if cfg!(debug_assertions) {
             info!("fully_perform({:?})", self);
         }
@@ -62,7 +62,7 @@ where
 fn scrape_region_constraints<'tcx, R>(
     infcx: &InferCtxt<'_, 'tcx>,
     op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
-) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+) -> Fallible<(R, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
     let mut fulfill_cx = TraitEngine::new(infcx.tcx);
     let dummy_body_id = ObligationCause::dummy().body_id;
 
@@ -92,7 +92,7 @@ fn scrape_region_constraints<'tcx, R>(
 
     let region_constraint_data = infcx.take_and_reset_region_constraints();
 
-    let outlives = query_response::make_query_outlives(
+    let region_constraints = query_response::make_query_region_constraints(
         infcx.tcx,
         region_obligations
             .iter()
@@ -101,9 +101,9 @@ fn scrape_region_constraints<'tcx, R>(
         &region_constraint_data,
     );
 
-    if outlives.is_empty() {
+    if region_constraints.is_empty() {
         Ok((value, None))
     } else {
-        Ok((value, Some(Rc::new(outlives))))
+        Ok((value, Some(Rc::new(region_constraints))))
     }
 }
diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs
index 4a07a3120f3..e2a5cd9670e 100644
--- a/src/librustc/traits/query/type_op/mod.rs
+++ b/src/librustc/traits/query/type_op/mod.rs
@@ -1,6 +1,6 @@
 use crate::infer::canonical::{
     Canonical, Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues,
-    QueryRegionConstraint, QueryResponse,
+    QueryRegionConstraints, QueryResponse,
 };
 use crate::infer::{InferCtxt, InferOk};
 use std::fmt;
@@ -32,7 +32,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
     fn fully_perform(
         self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)>;
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
 }
 
 /// "Query type ops" are type ops that are implemented using a
@@ -85,7 +85,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
     fn fully_perform_into(
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'_, 'tcx>,
-        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+        output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
     ) -> Fallible<Self::QueryResponse> {
         if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
             return Ok(result);
@@ -140,16 +140,16 @@ where
     fn fully_perform(
         self,
         infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
-        let mut qrc = vec![];
-        let r = Q::fully_perform_into(self, infcx, &mut qrc)?;
+    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+        let mut region_constraints = QueryRegionConstraints::default();
+        let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
 
         // Promote the final query-region-constraints into a
         // (optional) ref-counted vector:
-        let opt_qrc = if qrc.is_empty() {
+        let opt_qrc = if region_constraints.is_empty() {
             None
         } else {
-            Some(Rc::new(qrc))
+            Some(Rc::new(region_constraints))
         };
 
         Ok((r, opt_qrc))
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 7c4742259ac..798a25fe7b1 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -328,6 +328,23 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
     }
 }
 
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for SelectionCandidate<'tcx> {
+        (SelectionCandidate::BuiltinCandidate) { has_nested },
+        (SelectionCandidate::ParamCandidate)(poly_trait_ref),
+        (SelectionCandidate::ImplCandidate)(def_id),
+        (SelectionCandidate::AutoImplCandidate)(def_id),
+        (SelectionCandidate::ProjectionCandidate),
+        (SelectionCandidate::ClosureCandidate),
+        (SelectionCandidate::GeneratorCandidate),
+        (SelectionCandidate::FnPointerCandidate),
+        (SelectionCandidate::TraitAliasCandidate)(def_id),
+        (SelectionCandidate::ObjectCandidate),
+        (SelectionCandidate::BuiltinObjectCandidate),
+        (SelectionCandidate::BuiltinUnsizeCandidate),
+    }
+}
+
 struct SelectionCandidateSet<'tcx> {
     // a list of candidates that definitely apply to the current
     // obligation (meaning: types unify).
@@ -818,27 +835,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ty::Predicate::ConstEvaluatable(def_id, substs) => {
                 let tcx = self.tcx();
-                match tcx.lift_to_global(&(obligation.param_env, substs)) {
-                    Some((param_env, substs)) => {
-                        let instance =
-                            ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs);
-                        if let Some(instance) = instance {
-                            let cid = GlobalId {
-                                instance,
-                                promoted: None,
-                            };
-                            match self.tcx().const_eval(param_env.and(cid)) {
-                                Ok(_) => Ok(EvaluatedToOk),
-                                Err(_) => Ok(EvaluatedToErr),
-                            }
-                        } else {
-                            Ok(EvaluatedToErr)
+                if !(obligation.param_env, substs).has_local_value() {
+                    let param_env = obligation.param_env;
+                    let instance =
+                        ty::Instance::resolve(tcx, param_env, def_id, substs);
+                    if let Some(instance) = instance {
+                        let cid = GlobalId {
+                            instance,
+                            promoted: None,
+                        };
+                        match self.tcx().const_eval(param_env.and(cid)) {
+                            Ok(_) => Ok(EvaluatedToOk),
+                            Err(_) => Ok(EvaluatedToErr),
                         }
+                    } else {
+                        Ok(EvaluatedToErr)
                     }
-                    None => {
-                        // Inference variables still left in param_env or substs.
-                        Ok(EvaluatedToAmbig)
-                    }
+                } else {
+                    // Inference variables still left in param_env or substs.
+                    Ok(EvaluatedToAmbig)
                 }
             }
         }
@@ -1172,7 +1187,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         if self.can_use_global_caches(param_env) {
-            if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
+            if !trait_ref.has_local_value() {
                 debug!(
                     "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
                     trait_ref, result,
@@ -1645,8 +1660,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             if let Err(Overflow) = candidate {
                 // Don't cache overflow globally; we only produce this
                 // in certain modes.
-            } else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
-                if let Some(candidate) = tcx.lift_to_global(&candidate) {
+            } else if !trait_ref.has_local_value() {
+                if !candidate.has_local_value() {
                     debug!(
                         "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
                         trait_ref, candidate,
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 43bb4edd9b2..f0389bb037a 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -145,8 +145,8 @@ pub fn find_associated_item<'tcx>(
 /// Specialization is determined by the sets of types to which the impls apply;
 /// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
 /// to.
-pub(super) fn specializes<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(super) fn specializes(
+    tcx: TyCtxt<'_>,
     (impl1_def_id, impl2_def_id): (DefId, DefId),
 ) -> bool {
     debug!("specializes({:?}, {:?})", impl1_def_id, impl2_def_id);
@@ -282,10 +282,10 @@ fn fulfill_implication<'a, 'tcx>(
 }
 
 // Query provider for `specialization_graph_of`.
-pub(super) fn specialization_graph_provider<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub(super) fn specialization_graph_provider(
+    tcx: TyCtxt<'_>,
     trait_id: DefId,
-) -> &'tcx specialization_graph::Graph {
+) -> &specialization_graph::Graph {
     let mut sg = specialization_graph::Graph::new();
 
     let mut trait_impls = tcx.all_impls(trait_id);
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 2d295679be3..07d6f633143 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -417,7 +417,7 @@ pub struct SupertraitDefIds<'tcx> {
     visited: FxHashSet<DefId>,
 }
 
-pub fn supertrait_def_ids<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> SupertraitDefIds<'tcx> {
+pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
     SupertraitDefIds {
         tcx,
         stack: vec![trait_def_id],
diff --git a/src/librustc/ty/erase_regions.rs b/src/librustc/ty/erase_regions.rs
index 999b4eff856..3dd1fd100f2 100644
--- a/src/librustc/ty/erase_regions.rs
+++ b/src/librustc/ty/erase_regions.rs
@@ -42,10 +42,10 @@ impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
     }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if let Some(ty_lifted) = self.tcx.lift_to_global(&ty) {
-            self.tcx.erase_regions_ty(ty_lifted)
-        } else {
+        if ty.has_local_value() {
             ty.super_fold_with(self)
+        } else {
+            self.tcx.erase_regions_ty(ty)
         }
     }
 
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 8b98a2916a7..ab7df8e4e84 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn has_infer_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
+    fn has_local_value(&self) -> bool {
+        self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
+    }
     fn needs_infer(&self) -> bool {
         self.has_type_flags(
             TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER
@@ -922,6 +925,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
     }
 }
 
+// FIXME: Optimize for checking for infer flags
 struct HasTypeFlagsVisitor {
     flags: ty::TypeFlags,
 }
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index 13d93f173e8..b921272856e 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -1,5 +1,5 @@
 use crate::dep_graph::SerializedDepNodeIndex;
-use crate::dep_graph::DepNode;
+use crate::dep_graph::{DepKind, DepNode};
 use crate::hir::def_id::{CrateNum, DefId};
 use crate::ty::TyCtxt;
 use crate::ty::query::queries;
@@ -28,6 +28,9 @@ pub trait QueryConfig<'tcx> {
 }
 
 pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
+    const ANON: bool;
+    const EVAL_ALWAYS: bool;
+
     fn query(key: Self::Key) -> Query<'tcx>;
 
     // Don't use this method to access query results, instead use the methods on TyCtxt
@@ -35,6 +38,8 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
 
     fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;
 
+    fn dep_kind() -> DepKind;
+
     // Don't use this method to compute query results, instead use the methods on TyCtxt
     fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;
 
@@ -50,7 +55,7 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
     fn describe(tcx: TyCtxt<'_>, key: Self::Key) -> Cow<'static, str>;
 
     #[inline]
-    fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key) -> bool {
+    fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
         false
     }
 
@@ -75,33 +80,3 @@ impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
         "running analysis passes on this crate".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> {
-            #[inline]
-            fn cache_on_disk($tcx: TyCtxt<'tcx>, $key: Self::Key) -> bool {
-                $cond
-            }
-
-            #[inline]
-            fn try_load_from_disk(tcx: TyCtxt<'tcx>,
-                                      id: SerializedDepNodeIndex)
-                                      -> Option<Self::Value> {
-                tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
-            }
-        }
-    }
-);
-
-impl_disk_cacheable_query!(mir_borrowck, |tcx, def_id| {
-    def_id.is_local() && tcx.is_closure(def_id)
-});
-
-impl_disk_cacheable_query!(unsafety_check_result, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(borrowck, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(used_trait_imports, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(codegen_fn_attrs, |_, _| true);
-impl_disk_cacheable_query!(specialization_graph_of, |_, _| true);
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index e595b52876f..e788628bc58 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -101,6 +101,6 @@ pub use self::on_disk_cache::OnDiskCache;
 rustc_query_append! { [define_queries!][ <'tcx>
     Other {
         /// Runs analysis passes on the crate.
-        [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
+        [eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
     },
 ]}
diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs
index 982886f0f15..85153f99b19 100644
--- a/src/librustc/ty/query/on_disk_cache.rs
+++ b/src/librustc/ty/query/on_disk_cache.rs
@@ -221,26 +221,8 @@ impl<'sess> OnDiskCache<'sess> {
                 encode_query_results::<check_match<'_>, _>(tcx, enc, qri)?;
                 encode_query_results::<codegen_fn_attrs<'_>, _>(tcx, enc, qri)?;
                 encode_query_results::<specialization_graph_of<'_>, _>(tcx, enc, qri)?;
-
-                // const eval is special, it only encodes successfully evaluated constants
-                use crate::ty::query::QueryAccessors;
-                let cache = const_eval::query_cache(tcx).borrow();
-                assert!(cache.active.is_empty());
-                for (key, entry) in cache.results.iter() {
-                    use crate::ty::query::config::QueryDescription;
-                    if const_eval::cache_on_disk(tcx, key.clone()) {
-                        if let Ok(ref value) = entry.value {
-                            let dep_node = SerializedDepNodeIndex::new(entry.index.index());
-
-                            // Record position of the cache entry
-                            qri.push((dep_node, AbsoluteBytePos::new(enc.position())));
-
-                            // Encode the type check tables with the SerializedDepNodeIndex
-                            // as tag.
-                            enc.encode_tagged(dep_node, value)?;
-                        }
-                    }
-                }
+                encode_query_results::<const_eval<'_>, _>(tcx, enc, qri)?;
+                // FIXME: Include const_eval_raw?
 
                 Ok(())
             })?;
@@ -324,9 +306,9 @@ impl<'sess> OnDiskCache<'sess> {
     }
 
     /// Loads a diagnostic emitted during the previous compilation session.
-    pub fn load_diagnostics<'tcx>(
+    pub fn load_diagnostics(
         &self,
-        tcx: TyCtxt<'tcx>,
+        tcx: TyCtxt<'_>,
         dep_node_index: SerializedDepNodeIndex,
     ) -> Vec<Diagnostic> {
         let diagnostics: Option<EncodedDiagnostics> = self.load_indexed(
@@ -353,9 +335,9 @@ impl<'sess> OnDiskCache<'sess> {
 
     /// Returns the cached query result if there is something in the cache for
     /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
-    pub fn try_load_query_result<'tcx, T>(
+    pub fn try_load_query_result<T>(
         &self,
-        tcx: TyCtxt<'tcx>,
+        tcx: TyCtxt<'_>,
         dep_node_index: SerializedDepNodeIndex,
     ) -> Option<T>
     where
@@ -1090,7 +1072,7 @@ where
         let map = Q::query_cache(tcx).borrow();
         assert!(map.active.is_empty());
         for (key, entry) in map.results.iter() {
-            if Q::cache_on_disk(tcx, key.clone()) {
+            if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) {
                 let dep_node = SerializedDepNodeIndex::new(entry.index.index());
 
                 // Record position of the cache entry
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 7d5f984c1b6..0c9e31e1ff2 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -376,15 +376,13 @@ impl<'tcx> TyCtxt<'tcx> {
             return self.force_query_with_job::<Q>(key, job, null_dep_node).0;
         }
 
-        let dep_node = Q::to_dep_node(self, &key);
-
-        if dep_node.kind.is_anon() {
+        if Q::ANON {
             profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
             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| {
-                    tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                    tcx.dep_graph.with_anon_task(Q::dep_kind(), || {
                         Q::compute(tcx.global_tcx(), key)
                     })
                 })
@@ -405,7 +403,9 @@ impl<'tcx> TyCtxt<'tcx> {
             return result;
         }
 
-        if !dep_node.kind.is_eval_always() {
+        let dep_node = Q::to_dep_node(self, &key);
+
+        if !Q::EVAL_ALWAYS {
             // The diagnostics for this query will be
             // promoted to the current session during
             // try_mark_green(), so we can ignore them here.
@@ -444,7 +444,7 @@ impl<'tcx> TyCtxt<'tcx> {
         debug_assert!(self.dep_graph.is_green(dep_node));
 
         // First we try to load the result from the on-disk cache
-        let result = if Q::cache_on_disk(self.global_tcx(), key.clone()) &&
+        let result = if Q::cache_on_disk(self.global_tcx(), key.clone(), None) &&
                         self.sess.opts.debugging_opts.incremental_queries {
             self.sess.profiler(|p| p.incremental_load_result_start(Q::NAME));
             let result = Q::try_load_from_disk(self.global_tcx(), prev_dep_node_index);
@@ -546,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
             self.start_query(job.job.clone(), diagnostics, |tcx| {
-                if dep_node.kind.is_eval_always() {
+                if Q::EVAL_ALWAYS {
                     tcx.dep_graph.with_eval_always_task(dep_node,
                                                         tcx,
                                                         key,
@@ -569,8 +569,8 @@ impl<'tcx> TyCtxt<'tcx> {
             self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
         }
 
-        if dep_node.kind != crate::dep_graph::DepKind::Null {
-            if unlikely!(!diagnostics.is_empty()) {
+        if unlikely!(!diagnostics.is_empty()) {
+            if dep_node.kind != crate::dep_graph::DepKind::Null {
                 self.queries.on_disk_cache
                     .store_diagnostics(dep_node_index, diagnostics);
             }
@@ -589,15 +589,16 @@ impl<'tcx> TyCtxt<'tcx> {
     ///
     /// Note: The optimization is only available during incr. comp.
     pub(super) fn ensure_query<Q: QueryDescription<'tcx>>(self, key: Q::Key) -> () {
-        let dep_node = Q::to_dep_node(self, &key);
-
-        if dep_node.kind.is_eval_always() {
+        if Q::EVAL_ALWAYS {
             let _ = self.get_query::<Q>(DUMMY_SP, key);
             return;
         }
 
         // Ensuring an anonymous query makes no sense
-        assert!(!dep_node.kind.is_anon());
+        assert!(!Q::ANON);
+
+        let dep_node = Q::to_dep_node(self, &key);
+
         if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
             // A None return from `try_mark_green_and_read` means that this is either
             // a new dep node or that the dep node has already been marked red.
@@ -653,6 +654,30 @@ macro_rules! handle_cycle_error {
     };
 }
 
+macro_rules! is_anon {
+    ([]) => {{
+        false
+    }};
+    ([anon$(, $modifiers:ident)*]) => {{
+        true
+    }};
+    ([$other:ident$(, $modifiers:ident)*]) => {
+        is_anon!([$($modifiers),*])
+    };
+}
+
+macro_rules! is_eval_always {
+    ([]) => {{
+        false
+    }};
+    ([eval_always$(, $modifiers:ident)*]) => {{
+        true
+    }};
+    ([$other:ident$(, $modifiers:ident)*]) => {
+        is_eval_always!([$($modifiers),*])
+    };
+}
+
 macro_rules! hash_result {
     ([][$hcx:expr, $result:expr]) => {{
         dep_graph::hash_result($hcx, &$result)
@@ -933,6 +958,9 @@ macro_rules! define_queries_inner {
         }
 
         impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
+            const ANON: bool = is_anon!([$($modifiers)*]);
+            const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
+
             #[inline(always)]
             fn query(key: Self::Key) -> Query<'tcx> {
                 Query::$name(key)
@@ -951,6 +979,11 @@ macro_rules! define_queries_inner {
                 DepNode::new(tcx, $node(*key))
             }
 
+            #[inline(always)]
+            fn dep_kind() -> dep_graph::DepKind {
+                dep_graph::DepKind::$node
+            }
+
             #[inline]
             fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
                 __query_compute::$name(move || {
@@ -1133,7 +1166,7 @@ macro_rules! define_provider_struct {
 /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
 /// add it to the "We don't have enough information to reconstruct..." group in
 /// the match below.
-pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
+pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
     use crate::dep_graph::RecoverKey;
 
     // We must avoid ever having to call force_from_dep_node() for a
@@ -1210,66 +1243,3 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool
 
     true
 }
-
-
-// FIXME(#45015): Another piece of boilerplate code that could be generated in
-//                a combined define_dep_nodes!()/define_queries!() macro.
-macro_rules! impl_load_from_cache {
-    ($($dep_kind:ident => $query_name:ident,)*) => {
-        impl DepNode {
-            // Check whether the query invocation corresponding to the given
-            // DepNode is eligible for on-disk-caching.
-            pub fn cache_on_disk(&self, tcx: TyCtxt<'_>) -> bool {
-                use crate::ty::query::queries;
-                use crate::ty::query::QueryDescription;
-
-                match self.kind {
-                    $(DepKind::$dep_kind => {
-                        let def_id = self.extract_def_id(tcx).unwrap();
-                        queries::$query_name::cache_on_disk(tcx.global_tcx(), def_id)
-                    })*
-                    _ => false
-                }
-            }
-
-            // This is method will execute the query corresponding to the given
-            // DepNode. It is only expected to work for DepNodes where the
-            // above `cache_on_disk` methods returns true.
-            // Also, as a sanity check, it expects that the corresponding query
-            // invocation has been marked as green already.
-            pub fn load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
-                match self.kind {
-                    $(DepKind::$dep_kind => {
-                        debug_assert!(tcx.dep_graph
-                                         .node_color(self)
-                                         .map(|c| c.is_green())
-                                         .unwrap_or(false));
-
-                        let def_id = self.extract_def_id(tcx).unwrap();
-                        let _ = tcx.$query_name(def_id);
-                    })*
-                    _ => {
-                        bug!()
-                    }
-                }
-            }
-        }
-    }
-}
-
-impl_load_from_cache!(
-    typeck_tables_of => typeck_tables_of,
-    optimized_mir => optimized_mir,
-    unsafety_check_result => unsafety_check_result,
-    borrowck => borrowck,
-    mir_borrowck => mir_borrowck,
-    mir_const_qualif => mir_const_qualif,
-    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,
-    used_trait_imports => used_trait_imports,
-    codegen_fn_attrs => codegen_fn_attrs,
-    specialization_graph_of => specialization_graph_of,
-);
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 46adb7eb2a4..a6bfc2dee61 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -550,7 +550,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         if let ConstValue::Unevaluated(def_id, substs) = x.val {
             // FIXME(eddyb) get the right param_env.
             let param_env = ty::ParamEnv::empty();
-            if let Some(substs) = tcx.lift_to_global(&substs) {
+            if !substs.has_local_value() {
                 let instance = ty::Instance::resolve(
                     tcx.global_tcx(),
                     param_env,
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 3d8170586c4..28b52dcea80 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -15,6 +15,7 @@ use crate::mir::interpret;
 
 use std::fmt;
 use std::rc::Rc;
+use std::sync::Arc;
 
 impl fmt::Debug for ty::GenericParamDef {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -348,7 +349,7 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>, C: Lift<'tcx>> Lift<'tcx> for (A, B, C)
         tcx.lift(&self.0).and_then(|a| {
             tcx.lift(&self.1).and_then(|b| tcx.lift(&self.2).map(|c| (a, b, c)))
         })
-    }
+   }
 }
 
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
@@ -378,6 +379,20 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Box<T> {
     }
 }
 
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Rc<T> {
+    type Lifted = Rc<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&**self).map(Rc::new)
+    }
+}
+
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Arc<T> {
+    type Lifted = Arc<T::Lifted>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&**self).map(Arc::new)
+    }
+}
+
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
     type Lifted = Vec<T::Lifted>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
@@ -821,6 +836,13 @@ EnumTypeFoldableImpl! {
     } where T: TypeFoldable<'tcx>
 }
 
+EnumTypeFoldableImpl! {
+    impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
+        (Ok)(a),
+        (Err)(a),
+    } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
+}
+
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         Rc::new((**self).fold_with(folder))
@@ -831,6 +853,16 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
     }
 }
 
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
+        Arc::new((**self).fold_with(folder))
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        (**self).visit_with(visitor)
+    }
+}
+
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
     fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
         let content: T = (**self).fold_with(folder);
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 714b7c27200..a098cd17612 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -354,7 +354,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                                          cmt: &mc::cmt_<'tcx>,
                                          loan_region: ty::Region<'tcx>,
                                          borrow_span: Span) {
-        pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
+        pub fn borrow_of_local_data(cmt: &mc::cmt_<'_>) -> bool {
             match cmt.cat {
                 // Borrows of static items is allowed
                 Categorization::StaticItem => false,
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 3c7f19f7fbf..8763a6bc066 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -53,7 +53,7 @@ pub struct LoanDataFlowOperator;
 
 pub type LoanDataFlow<'tcx> = DataFlowContext<'tcx, LoanDataFlowOperator>;
 
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
     tcx.par_body_owners(|body_owner_def_id| {
         tcx.ensure().borrowck(body_owner_def_id);
     });
@@ -73,7 +73,7 @@ pub struct AnalysisData<'tcx> {
     pub move_data: move_data::FlowedMoveData<'tcx>,
 }
 
-fn borrowck<'tcx>(tcx: TyCtxt<'tcx>, owner_def_id: DefId) -> &'tcx BorrowCheckResult {
+fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult {
     assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
 
     debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs
index f5d311b35d7..dc7014d22ec 100644
--- a/src/librustc_borrowck/dataflow.rs
+++ b/src/librustc_borrowck/dataflow.rs
@@ -84,9 +84,9 @@ struct PropagationContext<'a, 'tcx, O> {
     changed: bool,
 }
 
-fn get_cfg_indices<'a>(id: hir::ItemLocalId,
-                       index: &'a FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
-                       -> &'a [CFGIndex] {
+fn get_cfg_indices(id: hir::ItemLocalId,
+                   index: &FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
+                   -> &[CFGIndex] {
     index.get(&id).map_or(&[], |v| &v[..])
 }
 
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index 4735588f29a..94abf1796d3 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -102,8 +102,8 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
         return
     }
 
-    // probestack doesn't play nice either with pgo-gen.
-    if cx.sess().opts.debugging_opts.pgo_gen.enabled() {
+    // probestack doesn't play nice either with `-C profile-generate`.
+    if cx.sess().opts.cg.profile_generate.enabled() {
         return;
     }
 
diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs
index e0e26e9af25..ca3b2b84655 100644
--- a/src/librustc_codegen_llvm/back/archive.rs
+++ b/src/librustc_codegen_llvm/back/archive.rs
@@ -205,8 +205,8 @@ impl<'a> LlvmArchiveBuilder<'a> {
     }
 
     fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
-        let removals = mem::replace(&mut self.removals, Vec::new());
-        let mut additions = mem::replace(&mut self.additions, Vec::new());
+        let removals = mem::take(&mut self.removals);
+        let mut additions = mem::take(&mut self.additions);
         let mut strings = Vec::new();
         let mut members = Vec::new();
 
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 3638730707f..b135605cf02 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -239,9 +239,9 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
     }
 }
 
-unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<LlvmCodegenBackend>,
-                                               msg: &'b str,
-                                               cookie: c_uint) {
+unsafe extern "C" fn report_inline_asm(cgcx: &CodegenContext<LlvmCodegenBackend>,
+                                       msg: &str,
+                                       cookie: c_uint) {
     cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
 }
 
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 04645dacfec..21c19e167cf 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -123,8 +123,8 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'tcx>, cgu_name: InternedString) {
 
     submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost);
 
-    fn module_codegen<'tcx>(
-        tcx: TyCtxt<'tcx>,
+    fn module_codegen(
+        tcx: TyCtxt<'_>,
         cgu_name: InternedString,
     ) -> ModuleCodegen<ModuleLlvm> {
         let cgu = tcx.codegen_unit(cgu_name);
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 0709368ad86..f67c740b777 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -144,7 +144,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn build_sibling_block<'b>(&self, name: &'b str) -> Self {
+    fn build_sibling_block(&self, name: &str) -> Self {
         Builder::new_block(self.cx, self.llfn(), name)
     }
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 7283aa95b30..ca63e589a6f 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -21,6 +21,7 @@
 #![feature(link_args)]
 #![feature(static_nobundle)]
 #![feature(trusted_len)]
+#![feature(mem_take)]
 #![deny(rust_2018_idioms)]
 #![deny(internal)]
 #![deny(unused_lifetimes)]
@@ -124,7 +125,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
     ) {
         unsafe { allocator::codegen(tcx, mods, kind) }
     }
-    fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: InternedString) {
+    fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString) {
         base::compile_codegen_unit(tcx, cgu_name);
     }
     fn target_machine_factory(
diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs
index 78570cce57d..d610805b5bb 100644
--- a/src/librustc_codegen_ssa/back/command.rs
+++ b/src/librustc_codegen_ssa/back/command.rs
@@ -110,7 +110,7 @@ impl Command {
     }
 
     pub fn take_args(&mut self) -> Vec<OsString> {
-        mem::replace(&mut self.args, Vec::new())
+        mem::take(&mut self.args)
     }
 
     /// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 618e8b8699f..707b7cae16c 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -653,10 +653,14 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
             linker_error.emit();
 
             if sess.target.target.options.is_like_msvc && linker_not_found {
-                sess.note_without_error("the msvc targets depend on the msvc linker \
-                    but `link.exe` was not found");
-                sess.note_without_error("please ensure that VS 2013, VS 2015 or VS 2017 \
-                    was installed with the Visual C++ option");
+                sess.note_without_error(
+                    "the msvc targets depend on the msvc linker \
+                     but `link.exe` was not found",
+                );
+                sess.note_without_error(
+                    "please ensure that VS 2013, VS 2015, VS 2017 or VS 2019 \
+                     was installed with the Visual C++ option",
+                );
             }
             sess.abort_if_errors();
         }
@@ -1179,7 +1183,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker,
         cmd.build_static_executable();
     }
 
-    if sess.opts.debugging_opts.pgo_gen.enabled() {
+    if sess.opts.cg.profile_generate.enabled() {
         cmd.pgo_gen();
     }
 
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index b9ee82f108a..b64c9a60d97 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -46,10 +46,10 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExpor
     }
 }
 
-fn reachable_non_generics_provider<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn reachable_non_generics_provider(
+    tcx: TyCtxt<'_>,
     cnum: CrateNum,
-) -> &'tcx DefIdMap<SymbolExportLevel> {
+) -> &DefIdMap<SymbolExportLevel> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     if !tcx.sess.opts.output_types.should_codegen() {
@@ -157,7 +157,7 @@ fn reachable_non_generics_provider<'tcx>(
     tcx.arena.alloc(reachable_non_generics)
 }
 
-fn is_reachable_non_generic_provider_local<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_reachable_non_generic_provider_local(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let export_threshold = threshold(tcx);
 
     if let Some(&level) = tcx.reachable_non_generics(def_id.krate).get(&def_id) {
@@ -167,14 +167,14 @@ fn is_reachable_non_generic_provider_local<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefI
     }
 }
 
-fn is_reachable_non_generic_provider_extern<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
 }
 
-fn exported_symbols_provider_local<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn exported_symbols_provider_local(
+    tcx: TyCtxt<'_>,
     cnum: CrateNum,
-) -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> {
+) -> Arc<Vec<(ExportedSymbol<'_>, SymbolExportLevel)>> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     if !tcx.sess.opts.output_types.should_codegen() {
@@ -203,7 +203,7 @@ fn exported_symbols_provider_local<'tcx>(
         }
     }
 
-    if tcx.sess.opts.debugging_opts.pgo_gen.enabled() {
+    if tcx.sess.opts.cg.profile_generate.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.
@@ -273,10 +273,10 @@ fn exported_symbols_provider_local<'tcx>(
     Arc::new(symbols)
 }
 
-fn upstream_monomorphizations_provider<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn upstream_monomorphizations_provider(
+    tcx: TyCtxt<'_>,
     cnum: CrateNum,
-) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+) -> &DefIdMap<FxHashMap<SubstsRef<'_>, CrateNum>> {
     debug_assert!(cnum == LOCAL_CRATE);
 
     let cnums = tcx.all_crate_nums(LOCAL_CRATE);
@@ -322,10 +322,10 @@ fn upstream_monomorphizations_provider<'tcx>(
     tcx.arena.alloc(instances)
 }
 
-fn upstream_monomorphizations_for_provider<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn upstream_monomorphizations_for_provider(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+) -> Option<&FxHashMap<SubstsRef<'_>, CrateNum>> {
     debug_assert!(!def_id.is_local());
     tcx.upstream_monomorphizations(LOCAL_CRATE).get(&def_id)
 }
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 309187ca2ea..fbf57701c5a 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -423,8 +423,8 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
         modules_config.passes.push("insert-gcov-profiling".to_owned())
     }
 
-    modules_config.pgo_gen = sess.opts.debugging_opts.pgo_gen.clone();
-    modules_config.pgo_use = sess.opts.debugging_opts.pgo_use.clone();
+    modules_config.pgo_gen = sess.opts.cg.profile_generate.clone();
+    modules_config.pgo_use = sess.opts.cg.profile_use.clone();
 
     modules_config.opt_level = Some(sess.opts.optimize);
     modules_config.opt_size = Some(sess.opts.optimize);
@@ -1345,12 +1345,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
                     assert!(!started_lto);
                     started_lto = true;
 
-                    let needs_fat_lto =
-                        mem::replace(&mut needs_fat_lto, Vec::new());
-                    let needs_thin_lto =
-                        mem::replace(&mut needs_thin_lto, Vec::new());
-                    let import_only_modules =
-                        mem::replace(&mut lto_import_only_modules, Vec::new());
+                    let needs_fat_lto = mem::take(&mut needs_fat_lto);
+                    let needs_thin_lto = mem::take(&mut needs_thin_lto);
+                    let import_only_modules = mem::take(&mut lto_import_only_modules);
 
                     for (work, cost) in generate_lto_work(&cgcx, needs_fat_lto,
                                                           needs_thin_lto, import_only_modules) {
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 47b383fddbc..d06460fc856 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -700,7 +700,7 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
     }
 }
 
-fn assert_and_save_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+fn assert_and_save_dep_graph(tcx: TyCtxt<'_>) {
     time(tcx.sess,
          "assert dep graph",
          || ::rustc_incremental::assert_dep_graph(tcx));
diff --git a/src/librustc_codegen_ssa/debuginfo/mod.rs b/src/librustc_codegen_ssa/debuginfo/mod.rs
index d60a2e0cb13..c9b1c0260e8 100644
--- a/src/librustc_codegen_ssa/debuginfo/mod.rs
+++ b/src/librustc_codegen_ssa/debuginfo/mod.rs
@@ -10,7 +10,7 @@ pub enum FunctionDebugContext<D> {
 }
 
 impl<D> FunctionDebugContext<D> {
-    pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<D> {
+    pub fn get_ref(&self, span: Span) -> &FunctionDebugContextData<D> {
         match *self {
             FunctionDebugContext::RegularContext(ref data) => data,
             FunctionDebugContext::DebugInfoDisabled => {
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index b76f098773f..3c1ab600040 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -10,6 +10,7 @@
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(trusted_len)]
+#![feature(mem_take)]
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 #![deny(rust_2018_idioms)]
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index 0289150a5e4..2af9b448ef1 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -273,7 +273,7 @@ impl CleanupKind {
     }
 }
 
-pub fn cleanup_kinds<'tcx>(mir: &mir::Body<'tcx>) -> IndexVec<mir::BasicBlock, CleanupKind> {
+pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKind> {
     fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
                               mir: &mir::Body<'tcx>) {
         for (bb, data) in mir.basic_blocks().iter_enumerated() {
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index 414871be611..9d5aaa7655d 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -44,7 +44,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
         mods: &mut Self::Module,
         kind: AllocatorKind,
     );
-    fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: InternedString);
+    fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString);
     // If find_features is true this won't access `sess.crate_types` by assuming
     // that `is_pie_binary` is false. When we discover LLVM target features
     // `sess.crate_types` is uninitialized so we cannot access it.
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 1c80e614db8..3a144f0b0e0 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -36,7 +36,7 @@ pub trait BuilderMethods<'a, 'tcx>:
 {
     fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
     fn with_cx(cx: &'a Self::CodegenCx) -> Self;
-    fn build_sibling_block<'b>(&self, name: &'b str) -> Self;
+    fn build_sibling_block(&self, name: &str) -> Self;
     fn cx(&self) -> &Self::CodegenCx;
     fn llbb(&self) -> Self::BasicBlock;
 
diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs
index f48d1f2853c..7ab29c5c4c3 100644
--- a/src/librustc_codegen_utils/symbol_names_test.rs
+++ b/src/librustc_codegen_utils/symbol_names_test.rs
@@ -11,7 +11,7 @@ use syntax::symbol::{Symbol, sym};
 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
 const DEF_PATH: Symbol = sym::rustc_def_path;
 
-pub fn report_symbol_names<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn report_symbol_names(tcx: TyCtxt<'_>) {
     // if the `rustc_attrs` feature is not enabled, then the
     // attributes we are interested in cannot be present anyway, so
     // skip the walk.
diff --git a/src/librustc_data_structures/binary_search_util/mod.rs b/src/librustc_data_structures/binary_search_util/mod.rs
new file mode 100644
index 00000000000..32aa1cb6b1d
--- /dev/null
+++ b/src/librustc_data_structures/binary_search_util/mod.rs
@@ -0,0 +1,49 @@
+#[cfg(test)]
+mod test;
+
+/// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The
+/// `key_fn` extracts a key of type `K` from the data, and this
+/// function finds the range of elements that match the key. `data`
+/// must have been sorted as if by a call to `sort_by_key` for this to
+/// work.
+pub fn binary_search_slice<E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E]
+where
+    K: Ord,
+{
+    let mid = match data.binary_search_by_key(key, &key_fn) {
+        Ok(mid) => mid,
+        Err(_) => return &[],
+    };
+
+    // We get back *some* element with the given key -- so
+    // search backwards to find the *first* one.
+    //
+    // (It'd be more efficient to use a "galloping" search
+    // here, but it's not really worth it for small-ish
+    // amounts of data.)
+    let mut start = mid;
+    while start > 0 {
+        if key_fn(&data[start - 1]) == *key {
+            start -= 1;
+        } else {
+            break;
+        }
+    }
+
+    // Now search forward to find the *last* one.
+    //
+    // (It'd be more efficient to use a "galloping" search
+    // here, but it's not really worth it for small-ish
+    // amounts of data.)
+    let mut end = mid + 1;
+    let max = data.len();
+    while end < max {
+        if key_fn(&data[end]) == *key {
+            end += 1;
+        } else {
+            break;
+        }
+    }
+
+    &data[start..end]
+}
diff --git a/src/librustc_data_structures/binary_search_util/test.rs b/src/librustc_data_structures/binary_search_util/test.rs
new file mode 100644
index 00000000000..d74febb5c0f
--- /dev/null
+++ b/src/librustc_data_structures/binary_search_util/test.rs
@@ -0,0 +1,23 @@
+use super::*;
+
+type Element = (usize, &'static str);
+
+fn test_map() -> Vec<Element> {
+    let mut data = vec![(3, "three-a"), (0, "zero"), (3, "three-b"), (22, "twenty-two")];
+    data.sort_by_key(get_key);
+    data
+}
+
+fn get_key(data: &Element) -> usize {
+    data.0
+}
+
+#[test]
+fn binary_search_slice_test() {
+    let map = test_map();
+    assert_eq!(binary_search_slice(&map, get_key, &0), &[(0, "zero")]);
+    assert_eq!(binary_search_slice(&map, get_key, &1), &[]);
+    assert_eq!(binary_search_slice(&map, get_key, &3), &[(3, "three-a"), (3, "three-b")]);
+    assert_eq!(binary_search_slice(&map, get_key, &22), &[(22, "twenty-two")]);
+    assert_eq!(binary_search_slice(&map, get_key, &23), &[]);
+}
diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs
index 5d8388d89f5..1eb28bccbe3 100644
--- a/src/librustc_data_structures/bit_set.rs
+++ b/src/librustc_data_structures/bit_set.rs
@@ -168,7 +168,7 @@ impl<T: Idx> BitSet<T> {
 
     /// Iterates over the indices of set bits in a sorted order.
     #[inline]
-    pub fn iter<'a>(&'a self) -> BitIter<'a, T> {
+    pub fn iter(&self) -> BitIter<'_, T> {
         BitIter {
             cur: None,
             iter: self.words.iter().enumerate(),
@@ -849,7 +849,7 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
 
     /// Iterates through all the columns set to true in a given row of
     /// the matrix.
-    pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
+    pub fn iter(&self, row: R) -> BitIter<'_, C> {
         assert!(row.index() < self.num_rows);
         let (start, end) = self.range(row);
         BitIter {
diff --git a/src/librustc_data_structures/fingerprint.rs b/src/librustc_data_structures/fingerprint.rs
index 7975c62b90f..3bea965ef30 100644
--- a/src/librustc_data_structures/fingerprint.rs
+++ b/src/librustc_data_structures/fingerprint.rs
@@ -58,7 +58,7 @@ impl Fingerprint {
         Ok(())
     }
 
-    pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
+    pub fn decode_opaque(decoder: &mut Decoder<'_>) -> Result<Fingerprint, String> {
         let mut bytes = [0; 16];
 
         decoder.read_raw_bytes(&mut bytes)?;
diff --git a/src/librustc_data_structures/graph/implementation/mod.rs b/src/librustc_data_structures/graph/implementation/mod.rs
index de4b1bcd0c2..d2699004c81 100644
--- a/src/librustc_data_structures/graph/implementation/mod.rs
+++ b/src/librustc_data_structures/graph/implementation/mod.rs
@@ -247,11 +247,11 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         self.incoming_edges(target).sources()
     }
 
-    pub fn depth_traverse<'a>(
-        &'a self,
+    pub fn depth_traverse(
+        &self,
         start: NodeIndex,
         direction: Direction,
-    ) -> DepthFirstTraversal<'a, N, E> {
+    ) -> DepthFirstTraversal<'_, N, E> {
         DepthFirstTraversal::with_start_node(self, start, direction)
     }
 
diff --git a/src/librustc_data_structures/graph/iterate/mod.rs b/src/librustc_data_structures/graph/iterate/mod.rs
index c09364b0a53..5612778ce07 100644
--- a/src/librustc_data_structures/graph/iterate/mod.rs
+++ b/src/librustc_data_structures/graph/iterate/mod.rs
@@ -1,5 +1,6 @@
 use super::super::indexed_vec::IndexVec;
-use super::{DirectedGraph, WithSuccessors, WithNumNodes};
+use super::{DirectedGraph, WithNumNodes, WithSuccessors};
+use crate::bit_set::BitSet;
 
 #[cfg(test)]
 mod test;
@@ -51,3 +52,36 @@ pub fn reverse_post_order<G: DirectedGraph + WithSuccessors + WithNumNodes>(
     vec.reverse();
     vec
 }
+
+/// A "depth-first search" iterator for a directed graph.
+pub struct DepthFirstSearch<'graph, G>
+where
+    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+    graph: &'graph G,
+    stack: Vec<G::Node>,
+    visited: BitSet<G::Node>,
+}
+
+impl<G> DepthFirstSearch<'graph, G>
+where
+    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+    pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
+        Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
+    }
+}
+
+impl<G> Iterator for DepthFirstSearch<'_, G>
+where
+    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+    type Item = G::Node;
+
+    fn next(&mut self) -> Option<G::Node> {
+        let DepthFirstSearch { stack, visited, graph } = self;
+        let n = stack.pop()?;
+        stack.extend(graph.successors(n).filter(|&m| visited.insert(m)));
+        Some(n)
+    }
+}
diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs
index 3d47b7d49fb..e59085a9e3a 100644
--- a/src/librustc_data_structures/graph/mod.rs
+++ b/src/librustc_data_structures/graph/mod.rs
@@ -5,6 +5,7 @@ pub mod implementation;
 pub mod iterate;
 mod reference;
 pub mod scc;
+pub mod vec_graph;
 
 #[cfg(test)]
 mod test;
@@ -17,14 +18,25 @@ pub trait WithNumNodes: DirectedGraph {
     fn num_nodes(&self) -> usize;
 }
 
+pub trait WithNumEdges: DirectedGraph {
+    fn num_edges(&self) -> usize;
+}
+
 pub trait WithSuccessors: DirectedGraph
 where
     Self: for<'graph> GraphSuccessors<'graph, Item = <Self as DirectedGraph>::Node>,
 {
-    fn successors<'graph>(
-        &'graph self,
+    fn successors(
+        &self,
         node: Self::Node,
-    ) -> <Self as GraphSuccessors<'graph>>::Iter;
+    ) -> <Self as GraphSuccessors<'_>>::Iter;
+
+    fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_, Self>
+    where
+        Self: WithNumNodes,
+    {
+        iterate::DepthFirstSearch::new(self, from)
+    }
 }
 
 pub trait GraphSuccessors<'graph> {
@@ -36,10 +48,10 @@ pub trait WithPredecessors: DirectedGraph
 where
     Self: for<'graph> GraphPredecessors<'graph, Item = <Self as DirectedGraph>::Node>,
 {
-    fn predecessors<'graph>(
-        &'graph self,
+    fn predecessors(
+        &self,
         node: Self::Node,
-    ) -> <Self as GraphPredecessors<'graph>>::Iter;
+    ) -> <Self as GraphPredecessors<'_>>::Iter;
 }
 
 pub trait GraphPredecessors<'graph> {
diff --git a/src/librustc_data_structures/graph/reference.rs b/src/librustc_data_structures/graph/reference.rs
index 5ad2a71e1d7..9442bb3cdec 100644
--- a/src/librustc_data_structures/graph/reference.rs
+++ b/src/librustc_data_structures/graph/reference.rs
@@ -17,15 +17,15 @@ impl<'graph, G: WithStartNode> WithStartNode for &'graph G {
 }
 
 impl<'graph, G: WithSuccessors> WithSuccessors for &'graph G {
-    fn successors<'iter>(&'iter self, node: Self::Node) -> <Self as GraphSuccessors<'iter>>::Iter {
+    fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
         (**self).successors(node)
     }
 }
 
 impl<'graph, G: WithPredecessors> WithPredecessors for &'graph G {
-    fn predecessors<'iter>(&'iter self,
-                           node: Self::Node)
-                           -> <Self as GraphPredecessors<'iter>>::Iter {
+    fn predecessors(&self,
+                    node: Self::Node)
+                    -> <Self as GraphPredecessors<'_>>::Iter {
         (**self).predecessors(node)
     }
 }
diff --git a/src/librustc_data_structures/graph/scc/mod.rs b/src/librustc_data_structures/graph/scc/mod.rs
index 24c5448639e..78554cda77b 100644
--- a/src/librustc_data_structures/graph/scc/mod.rs
+++ b/src/librustc_data_structures/graph/scc/mod.rs
@@ -4,7 +4,8 @@
 //! O(n) time.
 
 use crate::fx::FxHashSet;
-use crate::graph::{DirectedGraph, WithNumNodes, WithSuccessors};
+use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors};
+use crate::graph::vec_graph::VecGraph;
 use crate::indexed_vec::{Idx, IndexVec};
 use std::ops::Range;
 
@@ -58,6 +59,49 @@ impl<N: Idx, S: Idx> Sccs<N, S> {
     pub fn successors(&self, scc: S) -> &[S] {
         self.scc_data.successors(scc)
     }
+
+    /// Construct the reverse graph of the SCC graph.
+    pub fn reverse(&self) -> VecGraph<S> {
+        VecGraph::new(
+            self.num_sccs(),
+            self.all_sccs()
+                .flat_map(|source| self.successors(source).iter().map(move |&target| {
+                    (target, source)
+                }))
+                .collect(),
+        )
+    }
+}
+
+impl<N: Idx, S: Idx> DirectedGraph for Sccs<N, S> {
+    type Node = S;
+}
+
+impl<N: Idx, S: Idx> WithNumNodes for Sccs<N, S> {
+    fn num_nodes(&self) -> usize {
+        self.num_sccs()
+    }
+}
+
+impl<N: Idx, S: Idx> WithNumEdges for Sccs<N, S> {
+    fn num_edges(&self) -> usize {
+        self.scc_data.all_successors.len()
+    }
+}
+
+impl<N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs<N, S> {
+    type Item = S;
+
+    type Iter = std::iter::Cloned<std::slice::Iter<'graph, S>>;
+}
+
+impl<N: Idx, S: Idx> WithSuccessors for Sccs<N, S> {
+    fn successors<'graph>(
+        &'graph self,
+        node: S
+    ) -> <Self as GraphSuccessors<'graph>>::Iter {
+        self.successors(node).iter().cloned()
+    }
 }
 
 impl<S: Idx> SccData<S> {
diff --git a/src/librustc_data_structures/graph/test.rs b/src/librustc_data_structures/graph/test.rs
index b390c419572..bc142144e93 100644
--- a/src/librustc_data_structures/graph/test.rs
+++ b/src/librustc_data_structures/graph/test.rs
@@ -51,15 +51,15 @@ impl WithNumNodes for TestGraph {
 }
 
 impl WithPredecessors for TestGraph {
-    fn predecessors<'graph>(&'graph self,
-                            node: usize)
-                            -> <Self as GraphPredecessors<'graph>>::Iter {
+    fn predecessors(&self,
+                    node: usize)
+                    -> <Self as GraphPredecessors<'_>>::Iter {
         self.predecessors[&node].iter().cloned()
     }
 }
 
 impl WithSuccessors for TestGraph {
-    fn successors<'graph>(&'graph self, node: usize) -> <Self as GraphSuccessors<'graph>>::Iter {
+    fn successors(&self, node: usize) -> <Self as GraphSuccessors<'_>>::Iter {
         self.successors[&node].iter().cloned()
     }
 }
diff --git a/src/librustc_data_structures/graph/vec_graph/mod.rs b/src/librustc_data_structures/graph/vec_graph/mod.rs
new file mode 100644
index 00000000000..6fb1bb42d2c
--- /dev/null
+++ b/src/librustc_data_structures/graph/vec_graph/mod.rs
@@ -0,0 +1,113 @@
+use crate::indexed_vec::{Idx, IndexVec};
+use crate::graph::{DirectedGraph, WithNumNodes, WithNumEdges, WithSuccessors, GraphSuccessors};
+
+#[cfg(test)]
+mod test;
+
+pub struct VecGraph<N: Idx> {
+    /// Maps from a given node to an index where the set of successors
+    /// for that node starts. The index indexes into the `edges`
+    /// vector. To find the range for a given node, we look up the
+    /// start for that node and then the start for the next node
+    /// (i.e., with an index 1 higher) and get the range between the
+    /// two. This vector always has an extra entry so that this works
+    /// even for the max element.
+    node_starts: IndexVec<N, usize>,
+
+    edge_targets: Vec<N>,
+}
+
+impl<N: Idx> VecGraph<N> {
+    pub fn new(
+        num_nodes: usize,
+        mut edge_pairs: Vec<(N, N)>,
+    ) -> Self {
+        // Sort the edges by the source -- this is important.
+        edge_pairs.sort();
+
+        let num_edges = edge_pairs.len();
+
+        // Store the *target* of each edge into `edge_targets`.
+        let edge_targets: Vec<N> = edge_pairs.iter().map(|&(_, target)| target).collect();
+
+        // Create the *edge starts* array. We are iterating over over
+        // the (sorted) edge pairs. We maintain the invariant that the
+        // length of the `node_starts` arary is enough to store the
+        // current source node -- so when we see that the source node
+        // for an edge is greater than the current length, we grow the
+        // edge-starts array by just enough.
+        let mut node_starts = IndexVec::with_capacity(num_edges);
+        for (index, &(source, _)) in edge_pairs.iter().enumerate() {
+            // If we have a list like `[(0, x), (2, y)]`:
+            //
+            // - Start out with `node_starts` of `[]`
+            // - Iterate to `(0, x)` at index 0:
+            //   - Push one entry because `node_starts.len()` (0) is <= the source (0)
+            //   - Leaving us with `node_starts` of `[0]`
+            // - Iterate to `(2, y)` at index 1:
+            //   - Push one entry because `node_starts.len()` (1) is <= the source (2)
+            //   - Push one entry because `node_starts.len()` (2) is <= the source (2)
+            //   - Leaving us with `node_starts` of `[0, 1, 1]`
+            // - Loop terminates
+            while node_starts.len() <= source.index() {
+                node_starts.push(index);
+            }
+        }
+
+        // Pad out the `node_starts` array so that it has `num_nodes +
+        // 1` entries. Continuing our example above, if `num_nodes` is
+        // be `3`, we would push one more index: `[0, 1, 1, 2]`.
+        //
+        // Interpretation of that vector:
+        //
+        // [0, 1, 1, 2]
+        //        ---- range for N=2
+        //     ---- range for N=1
+        //  ---- range for N=0
+        while node_starts.len() <= num_nodes {
+            node_starts.push(edge_targets.len());
+        }
+
+        assert_eq!(node_starts.len(), num_nodes + 1);
+
+        Self { node_starts, edge_targets }
+    }
+
+    /// Gets the successors for `source` as a slice.
+    pub fn successors(&self, source: N) -> &[N] {
+        let start_index = self.node_starts[source];
+        let end_index = self.node_starts[source.plus(1)];
+        &self.edge_targets[start_index..end_index]
+    }
+}
+
+impl<N: Idx> DirectedGraph for VecGraph<N> {
+    type Node = N;
+}
+
+impl<N: Idx> WithNumNodes for VecGraph<N> {
+    fn num_nodes(&self) -> usize {
+        self.node_starts.len() - 1
+    }
+}
+
+impl<N: Idx> WithNumEdges for VecGraph<N> {
+    fn num_edges(&self) -> usize {
+        self.edge_targets.len()
+    }
+}
+
+impl<N: Idx> GraphSuccessors<'graph> for VecGraph<N> {
+    type Item = N;
+
+    type Iter = std::iter::Cloned<std::slice::Iter<'graph, N>>;
+}
+
+impl<N: Idx> WithSuccessors for VecGraph<N> {
+    fn successors<'graph>(
+        &'graph self,
+        node: N
+    ) -> <Self as GraphSuccessors<'graph>>::Iter {
+        self.successors(node).iter().cloned()
+    }
+}
diff --git a/src/librustc_data_structures/graph/vec_graph/test.rs b/src/librustc_data_structures/graph/vec_graph/test.rs
new file mode 100644
index 00000000000..97a9bd2ad0b
--- /dev/null
+++ b/src/librustc_data_structures/graph/vec_graph/test.rs
@@ -0,0 +1,51 @@
+use super::*;
+
+fn create_graph() -> VecGraph<usize> {
+    // Create a simple graph
+    //
+    //          5
+    //          |
+    //          V
+    //    0 --> 1 --> 2
+    //          |
+    //          v
+    //          3 --> 4
+    //
+    //    6
+
+    VecGraph::new(
+        7,
+        vec![
+            (0, 1),
+            (1, 2),
+            (1, 3),
+            (3, 4),
+            (5, 1),
+        ],
+    )
+}
+
+#[test]
+fn num_nodes() {
+    let graph = create_graph();
+    assert_eq!(graph.num_nodes(), 7);
+}
+
+#[test]
+fn succesors() {
+    let graph = create_graph();
+    assert_eq!(graph.successors(0), &[1]);
+    assert_eq!(graph.successors(1), &[2, 3]);
+    assert_eq!(graph.successors(2), &[]);
+    assert_eq!(graph.successors(3), &[4]);
+    assert_eq!(graph.successors(4), &[]);
+    assert_eq!(graph.successors(5), &[1]);
+    assert_eq!(graph.successors(6), &[]);
+}
+
+#[test]
+fn dfs() {
+    let graph = create_graph();
+    let dfs: Vec<_> = graph.depth_first_search(0).collect();
+    assert_eq!(dfs, vec![0, 1, 3, 4, 2]);
+}
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 635edbb927e..b3a810a622d 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -19,8 +19,11 @@ pub trait Idx: Copy + 'static + Ord + Debug + Hash {
     fn index(self) -> usize;
 
     fn increment_by(&mut self, amount: usize) {
-        let v = self.index() + amount;
-        *self = Self::new(v);
+        *self = self.plus(amount);
+    }
+
+    fn plus(self, amount: usize) -> Self {
+        Self::new(self.index() + amount)
     }
 }
 
@@ -167,6 +170,14 @@ macro_rules! newtype_index {
             }
         }
 
+        impl std::ops::Add<usize> for $type {
+            type Output = Self;
+
+            fn add(self, other: usize) -> Self {
+                Self::new(self.index() + other)
+            }
+        }
+
         impl Idx for $type {
             #[inline]
             fn new(value: usize) -> Self {
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index a1d7ab8856d..98c809f7e25 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -72,6 +72,7 @@ macro_rules! unlikely {
 pub mod macros;
 pub mod svh;
 pub mod base_n;
+pub mod binary_search_util;
 pub mod bit_set;
 pub mod box_region;
 pub mod const_cstr;
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index 0974607fabe..d7cbd1e2e4b 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -58,6 +58,10 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
         self.edges.is_empty()
     }
 
+    pub fn elements(&self) -> impl Iterator<Item=&T> {
+        self.elements.iter()
+    }
+
     fn index(&self, a: &T) -> Option<Index> {
         self.map.get(a).cloned()
     }
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index d92f3aafa1c..ff0c4ff548b 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -188,7 +188,7 @@ impl PpSourceMode {
             _ => panic!("Should use call_with_pp_support_hir"),
         }
     }
-    fn call_with_pp_support_hir<'tcx, A, F>(&self, tcx: TyCtxt<'tcx>, f: F) -> A
+    fn call_with_pp_support_hir<A, F>(&self, tcx: TyCtxt<'_>, f: F) -> A
     where
         F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A,
     {
@@ -228,7 +228,7 @@ impl PpSourceMode {
 trait PrinterSupport: pprust::PpAnn {
     /// Provides a uniform interface for re-extracting a reference to a
     /// `Session` from a value that now owns it.
-    fn sess<'a>(&'a self) -> &'a Session;
+    fn sess(&self) -> &Session;
 
     /// Produces the pretty-print annotation object.
     ///
@@ -240,7 +240,7 @@ trait PrinterSupport: pprust::PpAnn {
 trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
     /// Provides a uniform interface for re-extracting a reference to a
     /// `Session` from a value that now owns it.
-    fn sess<'a>(&'a self) -> &'a Session;
+    fn sess(&self) -> &Session;
 
     /// Provides a uniform interface for re-extracting a reference to an
     /// `hir_map::Map` from a value that now owns it.
@@ -272,7 +272,7 @@ struct NoAnn<'hir> {
 }
 
 impl<'hir> PrinterSupport for NoAnn<'hir> {
-    fn sess<'a>(&'a self) -> &'a Session {
+    fn sess(&self) -> &Session {
         self.sess
     }
 
@@ -282,7 +282,7 @@ impl<'hir> PrinterSupport for NoAnn<'hir> {
 }
 
 impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
-    fn sess<'a>(&'a self) -> &'a Session {
+    fn sess(&self) -> &Session {
         self.sess
     }
 
@@ -313,7 +313,7 @@ struct IdentifiedAnnotation<'hir> {
 }
 
 impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
-    fn sess<'a>(&'a self) -> &'a Session {
+    fn sess(&self) -> &Session {
         self.sess
     }
 
@@ -360,7 +360,7 @@ impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
 }
 
 impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
-    fn sess<'a>(&'a self) -> &'a Session {
+    fn sess(&self) -> &Session {
         self.sess
     }
 
@@ -458,7 +458,7 @@ struct TypedAnnotation<'a, 'tcx> {
 }
 
 impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
-    fn sess<'a>(&'a self) -> &'a Session {
+    fn sess(&self) -> &Session {
         &self.tcx.sess
     }
 
@@ -866,8 +866,8 @@ pub fn print_after_hir_lowering<'tcx>(
 // analysis is performed. However, we want to call `phase_3_run_analysis_passes`
 // with a different callback than the standard driver, so that isn't easy.
 // Instead, we call that function ourselves.
-fn print_with_analysis<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn print_with_analysis(
+    tcx: TyCtxt<'_>,
     ppm: PpMode,
     uii: Option<UserIdentifiedItem>,
     ofile: Option<&Path>,
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index a2717ab7ad8..83a0fb486fd 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -1635,7 +1635,7 @@ impl Destination {
         }
     }
 
-    fn writable<'a>(&'a mut self) -> WritableDst<'a> {
+    fn writable(&mut self) -> WritableDst<'_> {
         match *self {
             Destination::Terminal(ref mut t) => WritableDst::Terminal(t),
             Destination::Buffered(ref mut t) => {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 70bd25a9d57..1ffee1cdf69 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -438,14 +438,14 @@ impl Handler {
         self.err_count.store(0, SeqCst);
     }
 
-    pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
+    pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> {
         DiagnosticBuilder::new(self, Level::Cancelled, "")
     }
 
-    pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
-                                                    sp: S,
-                                                    msg: &str)
-                                                    -> DiagnosticBuilder<'a> {
+    pub fn struct_span_warn<S: Into<MultiSpan>>(&self,
+                                                sp: S,
+                                                msg: &str)
+                                                -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         result.set_span(sp);
         if !self.flags.can_emit_warnings {
@@ -453,11 +453,11 @@ impl Handler {
         }
         result
     }
-    pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                              sp: S,
-                                                              msg: &str,
-                                                              code: DiagnosticId)
-                                                              -> DiagnosticBuilder<'a> {
+    pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(&self,
+                                                          sp: S,
+                                                          msg: &str,
+                                                          code: DiagnosticId)
+                                                          -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         result.set_span(sp);
         result.code(code);
@@ -466,63 +466,63 @@ impl Handler {
         }
         result
     }
-    pub fn struct_warn<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         if !self.flags.can_emit_warnings {
             result.cancel();
         }
         result
     }
-    pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
-                                                   sp: S,
-                                                   msg: &str)
-                                                   -> DiagnosticBuilder<'a> {
+    pub fn struct_span_err<S: Into<MultiSpan>>(&self,
+                                               sp: S,
+                                               msg: &str)
+                                               -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
         result
     }
-    pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                             sp: S,
-                                                             msg: &str,
-                                                             code: DiagnosticId)
-                                                             -> DiagnosticBuilder<'a> {
+    pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
+                                                         sp: S,
+                                                         msg: &str,
+                                                         code: DiagnosticId)
+                                                         -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
         result.code(code);
         result
     }
     // FIXME: This method should be removed (every error should have an associated error code).
-    pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
         DiagnosticBuilder::new(self, Level::Error, msg)
     }
-    pub fn struct_err_with_code<'a>(
-        &'a self,
+    pub fn struct_err_with_code(
+        &self,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'a> {
+    ) -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.code(code);
         result
     }
-    pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
-                                                     sp: S,
-                                                     msg: &str)
-                                                     -> DiagnosticBuilder<'a> {
+    pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
+                                                 sp: S,
+                                                 msg: &str)
+                                                 -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
         result
     }
-    pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
-                                                               sp: S,
-                                                               msg: &str,
-                                                               code: DiagnosticId)
-                                                               -> DiagnosticBuilder<'a> {
+    pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(&self,
+                                                           sp: S,
+                                                           msg: &str,
+                                                           code: DiagnosticId)
+                                                           -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
         result.code(code);
         result
     }
-    pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
         DiagnosticBuilder::new(self, Level::Fatal, msg)
     }
 
@@ -563,10 +563,10 @@ impl Handler {
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Error);
     }
-    pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
-                                                sp: S,
-                                                msg: &str)
-                                                -> DiagnosticBuilder<'a> {
+    pub fn mut_span_err<S: Into<MultiSpan>>(&self,
+                                            sp: S,
+                                            msg: &str)
+                                            -> DiagnosticBuilder<'_> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
         result
@@ -605,10 +605,10 @@ impl Handler {
     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Note);
     }
-    pub fn span_note_diag<'a>(&'a self,
-                              sp: Span,
-                              msg: &str)
-                              -> DiagnosticBuilder<'a> {
+    pub fn span_note_diag(&self,
+                          sp: Span,
+                          msg: &str)
+                          -> DiagnosticBuilder<'_> {
         let mut db = DiagnosticBuilder::new(self, Note, msg);
         db.set_span(sp);
         db
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index a43347a2197..38dc6edaf63 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -51,7 +51,7 @@ use std::io::Write;
 use syntax::ast;
 use syntax_pos::Span;
 
-pub fn assert_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
     tcx.dep_graph.with_ignore(|| {
         if tcx.sess.opts.debugging_opts.dump_dep_graph {
             dump_graph(tcx);
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index f502d047546..046fdc72270 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -35,7 +35,7 @@ const MODULE: Symbol = sym::module;
 const CFG: Symbol = sym::cfg;
 const KIND: Symbol = sym::kind;
 
-pub fn assert_module_sources<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn assert_module_sources(tcx: TyCtxt<'_>) {
     tcx.dep_graph.with_ignore(|| {
         if tcx.sess.opts.incremental.is_none() {
             return;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 5296ed0ffd0..1d83aa112a8 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -206,7 +206,7 @@ impl Assertion {
     }
 }
 
-pub fn check_dirty_clean_annotations<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
     // can't add `#[rustc_dirty]` etc without opting in to this feature
     if !tcx.features().rustc_attrs {
         return;
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index d9bcc0b2a83..90aefb0f324 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -15,7 +15,7 @@ use super::fs::*;
 use super::file_format;
 use super::work_product;
 
-pub fn dep_graph_tcx_init<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn dep_graph_tcx_init(tcx: TyCtxt<'_>) {
     if !tcx.dep_graph.is_fully_enabled() {
         return
     }
@@ -192,7 +192,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     }))
 }
 
-pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess> {
+pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
     if sess.opts.incremental.is_none() ||
        !sess.opts.debugging_opts.incremental_queries {
         return OnDiskCache::new_empty(sess.source_map());
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 49c79ec09f5..13e2c5d1c57 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -15,7 +15,7 @@ use super::dirty_clean;
 use super::file_format;
 use super::work_product;
 
-pub fn save_dep_graph<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn save_dep_graph(tcx: TyCtxt<'_>) {
     debug!("save_dep_graph()");
     tcx.dep_graph.with_ignore(|| {
         let sess = tcx.sess;
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index c1b6e3409c9..d6987281981 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -878,7 +878,7 @@ pub fn create_global_ctxt(
 
 /// Runs the resolution, type-checking, region checking and other
 /// miscellaneous analysis passes on the crate.
-fn analysis<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Result<()> {
+fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     let sess = tcx.sess;
@@ -995,8 +995,8 @@ fn analysis<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Result<()> {
     Ok(())
 }
 
-fn encode_and_write_metadata<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn encode_and_write_metadata(
+    tcx: TyCtxt<'_>,
     outputs: &OutputFilenames,
 ) -> (middle::cstore::EncodedMetadata, bool) {
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
diff --git a/src/librustc_interface/proc_macro_decls.rs b/src/librustc_interface/proc_macro_decls.rs
index 9e1ef6b022d..d888c9e57d3 100644
--- a/src/librustc_interface/proc_macro_decls.rs
+++ b/src/librustc_interface/proc_macro_decls.rs
@@ -6,11 +6,11 @@ use rustc::ty::query::Providers;
 use syntax::attr;
 use syntax::symbol::sym;
 
-pub fn find<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DefId> {
+pub fn find(tcx: TyCtxt<'_>) -> Option<DefId> {
     tcx.proc_macro_decls_static(LOCAL_CRATE)
 }
 
-fn proc_macro_decls_static<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Option<DefId> {
+fn proc_macro_decls_static(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     let mut finder = Finder { decls: None };
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index a86d3cc4394..6ae5e94b11a 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -642,14 +642,14 @@ pub fn build_output_filenames(
                 );
                 None
             } else {
+                if !sess.opts.cg.extra_filename.is_empty() {
+                    sess.warn("ignoring -C extra-filename flag due to -o flag");
+                }
                 Some(out_file.clone())
             };
             if *odir != None {
                 sess.warn("ignoring --out-dir flag due to -o flag");
             }
-            if !sess.opts.cg.extra_filename.is_empty() {
-                sess.warn("ignoring -C extra-filename flag due to -o flag");
-            }
 
             OutputFilenames {
                 out_directory: out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index d808a15982e..4c6ceb14ca4 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -74,7 +74,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn lint_mod<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn lint_mod(tcx: TyCtxt<'_>, module_def_id: DefId) {
     lint::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
 }
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index b5c5fc0608b..2db2e0bc0da 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
         }
 
         let ty = cx.tables.expr_ty(&expr);
-        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "");
+        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "", "", false);
 
         let mut fn_warned = false;
         let mut op_warned = false;
@@ -133,7 +133,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
             ty: Ty<'tcx>,
             expr: &hir::Expr,
             span: Span,
-            descr_post_path: &str,
+            descr_pre: &str,
+            descr_post: &str,
+            plural: bool,
         ) -> bool {
             if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
                 cx.tcx.hir().get_module_parent(expr.hir_id), ty)
@@ -141,15 +143,29 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                 return true;
             }
 
+            let plural_suffix = if plural { "s" } else { "" };
+
             match ty.sty {
-                ty::Adt(def, _) => check_must_use_def(cx, def.did, span, "", descr_post_path),
+                ty::Adt(..) if ty.is_box() => {
+                    let boxed_ty = ty.boxed_ty();
+                    let descr_pre = &format!("{}boxed ", descr_pre);
+                    check_must_use_ty(cx, boxed_ty, expr, span, descr_pre, descr_post, plural)
+                }
+                ty::Adt(def, _) => {
+                    check_must_use_def(cx, def.did, span, descr_pre, descr_post)
+                }
                 ty::Opaque(def, _) => {
                     let mut has_emitted = false;
                     for (predicate, _) in &cx.tcx.predicates_of(def).predicates {
                         if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
                             let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
                             let def_id = trait_ref.def_id;
-                            if check_must_use_def(cx, def_id, span, "implementer of ", "") {
+                            let descr_pre = &format!(
+                                "{}implementer{} of ",
+                                descr_pre,
+                                plural_suffix,
+                            );
+                            if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
                                 has_emitted = true;
                                 break;
                             }
@@ -162,7 +178,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                     for predicate in binder.skip_binder().iter() {
                         if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
                             let def_id = trait_ref.def_id;
-                            if check_must_use_def(cx, def_id, span, "", " trait object") {
+                            let descr_post = &format!(
+                                " trait object{}{}",
+                                plural_suffix,
+                                descr_post,
+                            );
+                            if check_must_use_def(cx, def_id, span, descr_pre, descr_post) {
                                 has_emitted = true;
                                 break;
                             }
@@ -179,14 +200,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                         vec![]
                     };
                     for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
-                        let descr_post_path = &format!(" in tuple element {}", i);
+                        let descr_post = &format!(" in tuple element {}", i);
                         let span = *spans.get(i).unwrap_or(&span);
-                        if check_must_use_ty(cx, ty, expr, span, descr_post_path) {
+                        if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural) {
                             has_emitted = true;
                         }
                     }
                     has_emitted
                 }
+                ty::Array(ty, len) => match len.assert_usize(cx.tcx) {
+                    // If the array is definitely non-empty, we can do `#[must_use]` checking.
+                    Some(n) if n != 0 => {
+                        let descr_pre = &format!(
+                            "{}array{} of ",
+                            descr_pre,
+                            plural_suffix,
+                        );
+                        check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, true)
+                    }
+                    // Otherwise, we don't lint, to avoid false positives.
+                    _ => false,
+                }
                 _ => false,
             }
         }
diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs
index 98fba55218f..e9cf7bca25c 100644
--- a/src/librustc_macros/src/lib.rs
+++ b/src/librustc_macros/src/lib.rs
@@ -1,6 +1,8 @@
 #![feature(proc_macro_hygiene)]
 #![deny(rust_2018_idioms)]
 
+#![recursion_limit="128"]
+
 extern crate proc_macro;
 
 use synstructure::decl_derive;
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index 0474d2a2e3b..d47bd0580d6 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -1,4 +1,5 @@
 use proc_macro::TokenStream;
+use proc_macro2::{TokenTree, Delimiter};
 use syn::{
     Token, Ident, Type, Attribute, ReturnType, Expr, Block, Error,
     braced, parenthesized, parse_macro_input,
@@ -35,7 +36,7 @@ enum QueryModifier {
     Desc(Option<Ident>, Punctuated<Expr, Token![,]>),
 
     /// Cache the query to disk if the `Expr` returns true.
-    Cache(Option<Ident>, Expr),
+    Cache(Option<(IdentOrWild, IdentOrWild)>, Block),
 
     /// Custom code to load the query from disk.
     LoadCached(Ident, Ident, Block),
@@ -77,21 +78,26 @@ impl Parse for QueryModifier {
             };
             let desc = attr_content.parse_terminated(Expr::parse)?;
             Ok(QueryModifier::Desc(tcx, desc))
-        } else if modifier == "cache" {
+        } else if modifier == "cache_on_disk_if" {
             // Parse a cache modifier like:
-            // `cache { |tcx| key.is_local() }`
-            let attr_content;
-            braced!(attr_content in input);
-            let tcx = if attr_content.peek(Token![|]) {
-                attr_content.parse::<Token![|]>()?;
-                let tcx = attr_content.parse()?;
-                attr_content.parse::<Token![|]>()?;
-                Some(tcx)
+            // `cache(tcx, value) { |tcx| key.is_local() }`
+            let has_args = if let TokenTree::Group(group) = input.fork().parse()? {
+                group.delimiter() == Delimiter::Parenthesis
+            } else {
+                false
+            };
+            let args = if has_args {
+                let args;
+                parenthesized!(args in input);
+                let tcx = args.parse()?;
+                args.parse::<Token![,]>()?;
+                let value = args.parse()?;
+                Some((tcx, value))
             } else {
                 None
             };
-            let expr = attr_content.parse()?;
-            Ok(QueryModifier::Cache(tcx, expr))
+            let block = input.parse()?;
+            Ok(QueryModifier::Cache(args, block))
         } else if modifier == "load_cached" {
             // Parse a load_cached modifier like:
             // `load_cached(tcx, id) { tcx.queries.on_disk_cache.try_load_query_result(tcx, id) }`
@@ -203,8 +209,8 @@ struct QueryModifiers {
     /// The description of the query.
     desc: Option<(Option<Ident>, Punctuated<Expr, Token![,]>)>,
 
-    /// Cache the query to disk if the `Expr` returns true.
-    cache: Option<(Option<Ident>, Expr)>,
+    /// Cache the query to disk if the `Block` returns true.
+    cache: Option<(Option<(IdentOrWild, IdentOrWild)>, Block)>,
 
     /// Custom code to load the query from disk.
     load_cached: Option<(Ident, Ident, Block)>,
@@ -247,11 +253,11 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 load_cached = Some((tcx, id, block));
             }
-            QueryModifier::Cache(tcx, expr) => {
+            QueryModifier::Cache(args, expr) => {
                 if cache.is_some() {
                     panic!("duplicate modifier `cache` for query `{}`", query.name);
                 }
-                cache = Some((tcx, expr));
+                cache = Some((args, expr));
             }
             QueryModifier::Desc(tcx, list) => {
                 if desc.is_some() {
@@ -321,7 +327,7 @@ fn add_query_description_impl(
     let key = &query.key.0;
 
     // Find out if we should cache the query on disk
-    let cache = modifiers.cache.as_ref().map(|(tcx, expr)| {
+    let cache = modifiers.cache.as_ref().map(|(args, expr)| {
         let try_load_from_disk = if let Some((tcx, id, block)) = modifiers.load_cached.as_ref() {
             // Use custom code to load the query from disk
             quote! {
@@ -346,11 +352,22 @@ fn add_query_description_impl(
             }
         };
 
-        let tcx = tcx.as_ref().map(|t| quote! { #t }).unwrap_or(quote! { _ });
+        let tcx = args.as_ref().map(|t| {
+            let t = &(t.0).0;
+            quote! { #t }
+        }).unwrap_or(quote! { _ });
+        let value = args.as_ref().map(|t| {
+            let t = &(t.1).0;
+            quote! { #t }
+        }).unwrap_or(quote! { _ });
         quote! {
             #[inline]
             #[allow(unused_variables)]
-            fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: Self::Key) -> bool {
+            fn cache_on_disk(
+                #tcx: TyCtxt<'tcx>,
+                #key: Self::Key,
+                #value: Option<&Self::Value>
+            ) -> bool {
                 #expr
             }
 
@@ -395,6 +412,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
     let mut query_description_stream = quote! {};
     let mut dep_node_def_stream = quote! {};
     let mut dep_node_force_stream = quote! {};
+    let mut try_load_from_on_disk_cache_stream = quote! {};
     let mut no_force_queries = Vec::new();
 
     for group in groups.0 {
@@ -409,6 +427,22 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 _ => quote! { #result_full },
             };
 
+            if modifiers.cache.is_some() && !modifiers.no_force {
+                try_load_from_on_disk_cache_stream.extend(quote! {
+                    DepKind::#name => {
+                        debug_assert!(tcx.dep_graph
+                                         .node_color(self)
+                                         .map(|c| c.is_green())
+                                         .unwrap_or(false));
+
+                        let key = RecoverKey::recover(tcx.global_tcx(), self).unwrap();
+                        if queries::#name::cache_on_disk(tcx.global_tcx(), key, None) {
+                            let _ = tcx.#name(key);
+                        }
+                    }
+                });
+            }
+
             let mut attributes = Vec::new();
 
             // Pass on the fatal_cycle modifier
@@ -423,20 +457,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             if modifiers.no_hash {
                 attributes.push(quote! { no_hash });
             };
-
-            let mut attribute_stream = quote! {};
-
-            for e in attributes.into_iter().intersperse(quote! {,}) {
-                attribute_stream.extend(e);
-            }
-
-            // Add the query to the group
-            group_stream.extend(quote! {
-                [#attribute_stream] fn #name: #name(#arg) #result,
-            });
-
-            let mut attributes = Vec::new();
-
             // Pass on the anon modifier
             if modifiers.anon {
                 attributes.push(quote! { anon });
@@ -450,6 +470,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             for e in attributes.into_iter().intersperse(quote! {,}) {
                 attribute_stream.extend(e);
             }
+
+            // Add the query to the group
+            group_stream.extend(quote! {
+                [#attribute_stream] fn #name: #name(#arg) #result,
+            });
+
             // Create a dep node for the query
             dep_node_def_stream.extend(quote! {
                 [#attribute_stream] #name(#arg),
@@ -470,7 +496,11 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 });
             }
 
-            add_query_description_impl(&query, modifiers, &mut query_description_stream);
+            add_query_description_impl(
+                &query,
+                modifiers,
+                &mut query_description_stream,
+            );
         }
         let name = &group.name;
         query_stream.extend(quote! {
@@ -520,5 +550,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             }
         }
         #query_description_stream
+
+        impl DepNode {
+            /// Check whether the query invocation corresponding to the given
+            /// DepNode is eligible for on-disk-caching. If so, this is method
+            /// will execute the query corresponding to the given DepNode.
+            /// Also, as a sanity check, it expects that the corresponding query
+            /// invocation has been marked as green already.
+            pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
+                match self.kind {
+                    #try_load_from_on_disk_cache_stream
+                    _ => (),
+                }
+            }
+        }
     })
 }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index df0957254cc..2073b317939 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -868,7 +868,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.enabled()
+           self.sess.opts.cg.profile_generate.enabled()
         {
             info!("loading profiler");
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 04a9c4e9a1a..914084d7e9e 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -250,7 +250,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
 }
 
-pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
+pub fn provide(providers: &mut Providers<'_>) {
     // FIXME(#44234) - almost all of these queries have no sub-queries and
     // therefore no actual inputs, they're just reading tables calculated in
     // resolve! Does this work? Unsure! That's what the issue is about
@@ -550,7 +550,7 @@ impl CrateStore for cstore::CStore {
         self.do_postorder_cnums_untracked()
     }
 
-    fn encode_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>) -> EncodedMetadata {
+    fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata {
         encoder::encode_metadata(tcx)
     }
 
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index b52b6dfbb5e..73c20ccad5a 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1863,7 +1863,7 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
 // will allow us to slice the metadata to the precise length that we just
 // generated regardless of trailing bytes that end up in it.
 
-pub fn encode_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> EncodedMetadata {
+pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
     let mut encoder = opaque::Encoder::new(vec![]);
     encoder.emit_raw_bytes(METADATA_HEADER);
 
@@ -1905,7 +1905,7 @@ pub fn encode_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> EncodedMetadata {
     EncodedMetadata { raw_data: result }
 }
 
-pub fn get_repr_options<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> ReprOptions {
+pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
     let ty = tcx.type_of(did);
     match ty.sty {
         ty::Adt(ref def, _) => return def.repr,
diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs
index 0ce103cfa40..b1f4dfffc78 100644
--- a/src/librustc_metadata/foreign_modules.rs
+++ b/src/librustc_metadata/foreign_modules.rs
@@ -3,7 +3,7 @@ use rustc::hir;
 use rustc::middle::cstore::ForeignModule;
 use rustc::ty::TyCtxt;
 
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<ForeignModule> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
     let mut collector = Collector {
         tcx,
         modules: Vec::new(),
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index cd6270046fa..728fd004fcb 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -4,7 +4,7 @@ use rustc::ty::TyCtxt;
 use rustc_target::spec::abi::Abi;
 use syntax::symbol::sym;
 
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<String> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
     let mut collector = Collector {
         args: Vec::new(),
     };
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 7b335b3b483..4a01d0e559a 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -11,7 +11,7 @@ use syntax::feature_gate::{self, GateIssue};
 use syntax::symbol::{Symbol, sym};
 use syntax::{span_err, struct_span_err};
 
-pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<NativeLibrary> {
+pub fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector {
         tcx,
         libs: Vec::new(),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4872440f5bd..25ac93cc242 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -87,7 +87,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> {
+fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> {
     let input_body = tcx.mir_validated(def_id);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id));
 
@@ -275,7 +275,7 @@ fn do_mir_borrowck<'a, '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());
+    let reservation_warnings = mem::take(&mut mbcx.reservation_warnings);
     for (_, (place, span, location, bk, borrow)) in reservation_warnings {
         let mut initial_diag =
             mbcx.report_conflicting_borrow(location, (&place, span), bk, &borrow);
diff --git a/src/librustc_mir/borrow_check/nll/constraints/graph.rs b/src/librustc_mir/borrow_check/nll/constraints/graph.rs
index c4b2a5daef8..b5630251e58 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/graph.rs
+++ b/src/librustc_mir/borrow_check/nll/constraints/graph.rs
@@ -1,6 +1,6 @@
 use crate::borrow_check::nll::type_check::Locations;
-use crate::borrow_check::nll::constraints::ConstraintIndex;
-use crate::borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::OutlivesConstraintIndex;
+use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
 use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph;
@@ -12,8 +12,8 @@ use syntax_pos::DUMMY_SP;
 /// -> R2` or `R2 -> R1` depending on the direction type `D`.
 crate struct ConstraintGraph<D: ConstraintGraphDirecton> {
     _direction: D,
-    first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
-    next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
+    first_constraints: IndexVec<RegionVid, Option<OutlivesConstraintIndex>>,
+    next_constraints: IndexVec<OutlivesConstraintIndex, Option<OutlivesConstraintIndex>>,
 }
 
 crate type NormalConstraintGraph = ConstraintGraph<Normal>;
@@ -77,13 +77,13 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// reporting.
     crate fn new(
         direction: D,
-        set: &ConstraintSet,
+        set: &OutlivesConstraintSet,
         num_region_vars: usize,
     ) -> Self {
         let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
-        let mut next_constraints = IndexVec::from_elem(None, &set.constraints);
+        let mut next_constraints = IndexVec::from_elem(None, &set.outlives);
 
-        for (idx, constraint) in set.constraints.iter_enumerated().rev() {
+        for (idx, constraint) in set.outlives.iter_enumerated().rev() {
             let head = &mut first_constraints[D::start_region(constraint)];
             let next = &mut next_constraints[idx];
             debug_assert!(next.is_none());
@@ -103,7 +103,7 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// and not constraints.
     crate fn region_graph<'rg>(
         &'rg self,
-        set: &'rg ConstraintSet,
+        set: &'rg OutlivesConstraintSet,
         static_region: RegionVid,
     ) -> RegionGraph<'rg, D> {
         RegionGraph::new(set, self, static_region)
@@ -113,7 +113,7 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     crate fn outgoing_edges<'a>(
         &'a self,
         region_sup: RegionVid,
-        constraints: &'a ConstraintSet,
+        constraints: &'a OutlivesConstraintSet,
         static_region: RegionVid,
     ) -> Edges<'a, D> {
         //if this is the `'static` region and the graph's direction is normal,
@@ -142,8 +142,8 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
 
 crate struct Edges<'s, D: ConstraintGraphDirecton> {
     graph: &'s ConstraintGraph<D>,
-    constraints: &'s ConstraintSet,
-    pointer: Option<ConstraintIndex>,
+    constraints: &'s OutlivesConstraintSet,
+    pointer: Option<OutlivesConstraintIndex>,
     next_static_idx: Option<usize>,
     static_region: RegionVid,
 }
@@ -180,7 +180,7 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
 /// reverse) constraint graph. It implements the graph traits and is
 /// usd for doing the SCC computation.
 crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
-    set: &'s ConstraintSet,
+    set: &'s OutlivesConstraintSet,
     constraint_graph: &'s ConstraintGraph<D>,
     static_region: RegionVid,
 }
@@ -191,7 +191,7 @@ impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
     /// construct SCCs for region inference but also for error
     /// reporting.
     crate fn new(
-        set: &'s ConstraintSet,
+        set: &'s OutlivesConstraintSet,
         constraint_graph: &'s ConstraintGraph<D>,
         static_region: RegionVid,
     ) -> Self {
@@ -234,10 +234,10 @@ impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D>
 }
 
 impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
-    fn successors<'graph>(
-        &'graph self,
+    fn successors(
+        &self,
         node: Self::Node,
-    ) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
+    ) -> <Self as graph::GraphSuccessors<'_>>::Iter {
         self.outgoing_regions(node)
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/constraints/mod.rs b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
index b1091eb5ac8..6121ed0cf0d 100644
--- a/src/librustc_mir/borrow_check/nll/constraints/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/constraints/mod.rs
@@ -1,37 +1,40 @@
+use crate::borrow_check::nll::type_check::Locations;
 use rustc::mir::ConstraintCategory;
 use rustc::ty::RegionVid;
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use crate::borrow_check::nll::type_check::Locations;
-
 use std::fmt;
-use std::ops::Deref;
+use std::ops::Index;
 
 crate mod graph;
 
+/// A set of NLL region constraints. These include "outlives"
+/// constraints of the form `R1: R2`. Each constraint is identified by
+/// a unique `OutlivesConstraintIndex` and you can index into the set
+/// (`constraint_set[i]`) to access the constraint details.
 #[derive(Clone, Default)]
-crate struct ConstraintSet {
-    constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
+crate struct OutlivesConstraintSet {
+    outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint>,
 }
 
-impl ConstraintSet {
+impl OutlivesConstraintSet {
     crate fn push(&mut self, constraint: OutlivesConstraint) {
         debug!(
-            "ConstraintSet::push({:?}: {:?} @ {:?}",
+            "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
             constraint.sup, constraint.sub, constraint.locations
         );
         if constraint.sup == constraint.sub {
             // 'a: 'a is pretty uninteresting
             return;
         }
-        self.constraints.push(constraint);
+        self.outlives.push(constraint);
     }
 
     /// Constructs a "normal" graph from the constraint set; the graph makes it
     /// easy to find the constraints affecting a particular region.
     ///
     /// N.B., this graph contains a "frozen" view of the current
-    /// constraints. Any new constraints added to the `ConstraintSet`
+    /// constraints. Any new constraints added to the `OutlivesConstraintSet`
     /// after the graph is built will not be present in the graph.
     crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph {
         graph::ConstraintGraph::new(graph::Normal, self, num_region_vars)
@@ -54,13 +57,17 @@ impl ConstraintSet {
         let region_graph = &constraint_graph.region_graph(self, static_region);
         Sccs::new(region_graph)
     }
+
+    crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint> {
+        &self.outlives
+    }
 }
 
-impl Deref for ConstraintSet {
-    type Target = IndexVec<ConstraintIndex, OutlivesConstraint>;
+impl Index<OutlivesConstraintIndex> for OutlivesConstraintSet {
+    type Output = OutlivesConstraint;
 
-    fn deref(&self) -> &Self::Target {
-        &self.constraints
+    fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output {
+        &self.outlives[i]
     }
 }
 
@@ -94,8 +101,8 @@ impl fmt::Debug for OutlivesConstraint {
 }
 
 newtype_index! {
-    pub struct ConstraintIndex {
-        DEBUG_FORMAT = "ConstraintIndex({})"
+    pub struct OutlivesConstraintIndex {
+        DEBUG_FORMAT = "OutlivesConstraintIndex({})"
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/member_constraints.rs b/src/librustc_mir/borrow_check/nll/member_constraints.rs
new file mode 100644
index 00000000000..b5e2e111f38
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/member_constraints.rs
@@ -0,0 +1,235 @@
+use crate::rustc::ty::{self, Ty};
+use rustc::hir::def_id::DefId;
+use rustc::infer::region_constraints::MemberConstraint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use std::hash::Hash;
+use std::ops::Index;
+use syntax_pos::Span;
+
+/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
+/// indexed by the region `R0`.
+crate struct MemberConstraintSet<'tcx, R>
+where
+    R: Copy + Hash + Eq,
+{
+    /// Stores the first "member" constraint for a given `R0`. This is an
+    /// index into the `constraints` vector below.
+    first_constraints: FxHashMap<R, NllMemberConstraintIndex>,
+
+    /// Stores the data about each `R0 member of [R1..Rn]` constraint.
+    /// These are organized into a linked list, so each constraint
+    /// contains the index of the next constraint with the same `R0`.
+    constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
+
+    /// Stores the `R1..Rn` regions for *all* sets. For any given
+    /// constraint, we keep two indices so that we can pull out a
+    /// slice.
+    choice_regions: Vec<ty::RegionVid>,
+}
+
+/// Represents a `R0 member of [R1..Rn]` constraint
+crate struct NllMemberConstraint<'tcx> {
+    next_constraint: Option<NllMemberConstraintIndex>,
+
+    /// The opaque type whose hidden type is being inferred. (Used in error reporting.)
+    crate opaque_type_def_id: DefId,
+
+    /// The span where the hidden type was instantiated.
+    crate definition_span: Span,
+
+    /// The hidden type in which `R0` appears. (Used in error reporting.)
+    crate hidden_ty: Ty<'tcx>,
+
+    /// The region `R0`.
+    crate member_region_vid: ty::RegionVid,
+
+    /// Index of `R1` in `choice_regions` vector from `MemberConstraintSet`.
+    start_index: usize,
+
+    /// Index of `Rn` in `choice_regions` vector from `MemberConstraintSet`.
+    end_index: usize,
+}
+
+newtype_index! {
+    crate struct NllMemberConstraintIndex {
+        DEBUG_FORMAT = "MemberConstraintIndex({})"
+    }
+}
+
+impl Default for MemberConstraintSet<'tcx, ty::RegionVid> {
+    fn default() -> Self {
+        Self {
+            first_constraints: Default::default(),
+            constraints: Default::default(),
+            choice_regions: Default::default(),
+        }
+    }
+}
+
+impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
+    /// Pushes a member constraint into the set.
+    ///
+    /// The input member constraint `m_c` is in the form produced by
+    /// the the `rustc::infer` code.
+    ///
+    /// The `to_region_vid` callback fn is used to convert the regions
+    /// within into `RegionVid` format -- it typically consults the
+    /// `UniversalRegions` data structure that is known to the caller
+    /// (but which this code is unaware of).
+    crate fn push_constraint(
+        &mut self,
+        m_c: &MemberConstraint<'tcx>,
+        mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
+    ) {
+        debug!("push_constraint(m_c={:?})", m_c);
+        let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
+        let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
+        let start_index = self.choice_regions.len();
+        let end_index = start_index + m_c.choice_regions.len();
+        debug!("push_constraint: member_region_vid={:?}", member_region_vid);
+        let constraint_index = self.constraints.push(NllMemberConstraint {
+            next_constraint,
+            member_region_vid,
+            opaque_type_def_id: m_c.opaque_type_def_id,
+            definition_span: m_c.definition_span,
+            hidden_ty: m_c.hidden_ty,
+            start_index,
+            end_index,
+        });
+        self.first_constraints.insert(member_region_vid, constraint_index);
+        self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
+    }
+}
+
+impl<R1> MemberConstraintSet<'tcx, R1>
+where
+    R1: Copy + Hash + Eq,
+{
+    /// Remap the "member region" key using `map_fn`, producing a new
+    /// member constraint set.  This is used in the NLL code to map from
+    /// the original `RegionVid` to an scc index. In some cases, we
+    /// may have multiple `R1` values mapping to the same `R2` key -- that
+    /// is ok, the two sets will be merged.
+    crate fn into_mapped<R2>(
+        self,
+        mut map_fn: impl FnMut(R1) -> R2,
+    ) -> MemberConstraintSet<'tcx, R2>
+    where
+        R2: Copy + Hash + Eq,
+    {
+        // We can re-use most of the original data, just tweaking the
+        // linked list links a bit.
+        //
+        // For example if we had two keys `Ra` and `Rb` that both now
+        // wind up mapped to the same key `S`, we would append the
+        // linked list for `Ra` onto the end of the linked list for
+        // `Rb` (or vice versa) -- this basically just requires
+        // rewriting the final link from one list to point at the othe
+        // other (see `append_list`).
+
+        let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
+
+        let mut first_constraints2 = FxHashMap::default();
+        first_constraints2.reserve(first_constraints.len());
+
+        for (r1, start1) in first_constraints {
+            let r2 = map_fn(r1);
+            if let Some(&start2) = first_constraints2.get(&r2) {
+                append_list(&mut constraints, start1, start2);
+            }
+            first_constraints2.insert(r2, start1);
+        }
+
+        MemberConstraintSet {
+            first_constraints: first_constraints2,
+            constraints,
+            choice_regions,
+        }
+    }
+}
+
+impl<R> MemberConstraintSet<'tcx, R>
+where
+    R: Copy + Hash + Eq,
+{
+    crate fn all_indices(
+        &self,
+    ) -> impl Iterator<Item = NllMemberConstraintIndex> {
+        self.constraints.indices()
+    }
+
+    /// Iterate down the constraint indices associated with a given
+    /// peek-region.  You can then use `choice_regions` and other
+    /// methods to access data.
+    crate fn indices(
+        &self,
+        member_region_vid: R,
+    ) -> impl Iterator<Item = NllMemberConstraintIndex> + '_ {
+        let mut next = self.first_constraints.get(&member_region_vid).cloned();
+        std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
+            if let Some(current) = next {
+                next = self.constraints[current].next_constraint;
+                Some(current)
+            } else {
+                None
+            }
+        })
+    }
+
+    /// Returns the "choice regions" for a given member
+    /// constraint. This is the `R1..Rn` from a constraint like:
+    ///
+    /// ```
+    /// R0 member of [R1..Rn]
+    /// ```
+    crate fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
+        let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
+        &self.choice_regions[*start_index..*end_index]
+    }
+}
+
+impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
+where
+    R: Copy + Hash + Eq,
+{
+    type Output = NllMemberConstraint<'tcx>;
+
+    fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
+        &self.constraints[i]
+    }
+}
+
+/// Given a linked list starting at `source_list` and another linked
+/// list starting at `target_list`, modify `target_list` so that it is
+/// followed by `source_list`.
+///
+/// Before:
+///
+/// ```
+/// target_list: A -> B -> C -> (None)
+/// source_list: D -> E -> F -> (None)
+/// ```
+///
+/// After:
+///
+/// ```
+/// target_list: A -> B -> C -> D -> E -> F -> (None)
+/// ```
+fn append_list(
+    constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
+    target_list: NllMemberConstraintIndex,
+    source_list: NllMemberConstraintIndex,
+) {
+    let mut p = target_list;
+    loop {
+        let mut r = &mut constraints[p];
+        match r.next_constraint {
+            Some(q) => p = q,
+            None => {
+                r.next_constraint = Some(source_list);
+                return;
+            }
+        }
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 5dd7b745273..eb63e0de195 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -37,6 +37,7 @@ crate mod type_check;
 mod universal_regions;
 
 mod constraints;
+mod member_constraints;
 
 use self::facts::AllFacts;
 use self::region_infer::RegionInferenceContext;
@@ -129,6 +130,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
         placeholder_index_to_region: _,
         mut liveness_constraints,
         outlives_constraints,
+        member_constraints,
         closure_bounds_mapping,
         type_tests,
     } = constraints;
@@ -150,6 +152,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
         universal_region_relations,
         body,
         outlives_constraints,
+        member_constraints,
         closure_bounds_mapping,
         type_tests,
         liveness_constraints,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
index 4931005a454..d4f6ce8801e 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
@@ -71,7 +71,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
         }
 
-        let mut constraints: Vec<_> = self.constraints.iter().collect();
+        let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort();
         for constraint in &constraints {
             let OutlivesConstraint {
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 04ff54e9a5e..9e08961f440 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
@@ -1,4 +1,5 @@
 use crate::borrow_check::nll::constraints::OutlivesConstraint;
+use crate::borrow_check::nll::region_infer::AppliedMemberConstraint;
 use crate::borrow_check::nll::region_infer::RegionInferenceContext;
 use crate::borrow_check::nll::type_check::Locations;
 use crate::borrow_check::nll::universal_regions::DefiningTy;
@@ -195,6 +196,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         Trace::NotVisited => {
                             bug!("found unvisited region {:?} on path to {:?}", p, r)
                         }
+
                         Trace::FromOutlivesConstraint(c) => {
                             result.push(c);
                             p = c.sup;
@@ -211,10 +213,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // Otherwise, walk over the outgoing constraints and
             // enqueue any regions we find, keeping track of how we
             // reached them.
+
+            // A constraint like `'r: 'x` can come from our constraint
+            // graph.
             let fr_static = self.universal_regions.fr_static;
-            for constraint in self.constraint_graph
-                .outgoing_edges(r, &self.constraints, fr_static)
-            {
+            let outgoing_edges_from_graph = self.constraint_graph
+                .outgoing_edges(r, &self.constraints, fr_static);
+
+
+            // But member constraints can also give rise to `'r: 'x`
+            // edges that were not part of the graph initially, so
+            // watch out for those.
+            let outgoing_edges_from_picks = self.applied_member_constraints(r)
+                .iter()
+                .map(|&AppliedMemberConstraint { min_choice, member_constraint_index, .. }| {
+                    let p_c = &self.member_constraints[member_constraint_index];
+                    OutlivesConstraint {
+                        sup: r,
+                        sub: min_choice,
+                        locations: Locations::All(p_c.definition_span),
+                        category: ConstraintCategory::OpaqueType,
+                    }
+                });
+
+            for constraint in outgoing_edges_from_graph.chain(outgoing_edges_from_picks) {
                 debug_assert_eq!(constraint.sup, r);
                 let sub_region = constraint.sub;
                 if let Trace::NotVisited = context[sub_region] {
@@ -687,7 +709,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     // Finds some region R such that `fr1: R` and `R` is live at
     // `elem`.
-    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+    crate fn find_sub_region_live_at(
+        &self,
+        fr1: RegionVid,
+        elem: Location,
+    ) -> RegionVid {
         debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
         self.find_constraint_paths_between_regions(fr1, |r| {
             // First look for some `r` such that `fr1: r` and `r` is live at `elem`
@@ -729,8 +755,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr1: RegionVid,
         fr2: RegionVid,
     ) -> (ConstraintCategory, Span) {
-        let (category, _, span) =
-            self.best_blame_constraint(body, fr1, |r| self.provides_universal_region(r, fr1, fr2));
+        let (category, _, span) = self.best_blame_constraint(
+            body,
+            fr1,
+            |r| self.provides_universal_region(r, fr1, fr2),
+        );
         (category, span)
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
index 0cf8a0d16f6..fdf2af9f44e 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
@@ -63,7 +63,7 @@ impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
         vids.into()
     }
     fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
-        (&self.regioncx.constraints.raw[..]).into()
+        (&self.regioncx.constraints.outlives().raw[..]).into()
     }
 
     // Render `a: b` as `a -> b`, indicating the flow
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 41ed564d0f0..4e609460c1f 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1,25 +1,32 @@
 use super::universal_regions::UniversalRegions;
 use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
-use crate::borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::{
+    ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
+};
+use crate::borrow_check::nll::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
 use crate::borrow_check::nll::region_infer::values::{
-    PlaceholderIndices, RegionElement, ToElementIndex
+    PlaceholderIndices, RegionElement, ToElementIndex,
 };
-use crate::borrow_check::Upvar;
 use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
 use crate::borrow_check::nll::type_check::Locations;
+use crate::borrow_check::Upvar;
 use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryOutlivesConstraint;
+use rustc::infer::opaque_types;
 use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
 use rustc::mir::{
-    ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
-    ConstraintCategory, Local, Location, Body,
+    Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
+    ConstraintCategory, Local, Location,
 };
 use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc::util::common::{self, ErrorReported};
+use rustc_data_structures::binary_search_util;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::graph::WithSuccessors;
 use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::vec_graph::VecGraph;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_errors::{Diagnostic, DiagnosticBuilder};
 use syntax_pos::Span;
@@ -49,17 +56,31 @@ pub struct RegionInferenceContext<'tcx> {
     liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Rc<ConstraintSet>,
+    constraints: Rc<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
     constraint_graph: Rc<NormalConstraintGraph>,
 
-    /// The SCC computed from `constraints` and the constraint graph. Used to
+    /// The SCC computed from `constraints` and the constraint
+    /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
     constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
+    /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
+    /// exists if `B: A`. Computed lazilly.
+    rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+
+    /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
+    member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+
+    /// Records the member constraints that we applied to each scc.
+    /// This is useful for error reporting. Once constraint
+    /// propagation is done, this vector is sorted according to
+    /// `member_region_scc`.
+    member_constraints_applied: Vec<AppliedMemberConstraint>,
+
     /// Map closure bounds to a `Span` that should be used for error reporting.
     closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
@@ -95,6 +116,32 @@ pub struct RegionInferenceContext<'tcx> {
     universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
 }
 
+/// Each time that `apply_member_constraint` is successful, it appends
+/// one of these structs to the `member_constraints_applied` field.
+/// This is used in error reporting to trace out what happened.
+///
+/// The way that `apply_member_constraint` works is that it effectively
+/// adds a new lower bound to the SCC it is analyzing: so you wind up
+/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
+/// minimal viable option.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+struct AppliedMemberConstraint {
+    /// The SCC that was affected. (The "member region".)
+    ///
+    /// The vector if `AppliedMemberConstraint` elements is kept sorted
+    /// by this field.
+    member_region_scc: ConstraintSccIndex,
+
+    /// The "best option" that `apply_member_constraint` found -- this was
+    /// added as an "ad-hoc" lower-bound to `member_region_scc`.
+    min_choice: ty::RegionVid,
+
+    /// The "member constraint index" -- we can find out details about
+    /// the constraint from
+    /// `set.member_constraints[member_constraint_index]`.
+    member_constraint_index: NllMemberConstraintIndex,
+}
+
 struct RegionDefinition<'tcx> {
     /// What kind of variable is this -- a free region? existential
     /// variable? etc. (See the `NLLRegionVariableOrigin` for more
@@ -186,7 +233,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         placeholder_indices: Rc<PlaceholderIndices>,
         universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
         _body: &Body<'tcx>,
-        outlives_constraints: ConstraintSet,
+        outlives_constraints: OutlivesConstraintSet,
+        member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
         closure_bounds_mapping: FxHashMap<
             Location,
             FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
@@ -218,12 +266,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
 
+        let member_constraints =
+            Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
+
         let mut result = Self {
             definitions,
             liveness_constraints,
             constraints,
             constraint_graph,
             constraint_sccs,
+            rev_constraint_graph: None,
+            member_constraints,
+            member_constraints_applied: Vec::new(),
             closure_bounds_mapping,
             scc_universes,
             scc_representatives,
@@ -341,9 +395,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         debug!(
                             "init_free_and_bound_regions: placeholder {:?} is \
                              not compatible with universe {:?} of its SCC {:?}",
-                            placeholder,
-                            scc_universe,
-                            scc,
+                            placeholder, scc_universe, scc,
                         );
                         self.add_incompatible_universe(scc);
                     }
@@ -394,6 +446,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.scc_universes[scc]
     }
 
+    /// Once region solving has completed, this function will return
+    /// the member constraints that were applied to the value of a given
+    /// region `r`. See `AppliedMemberConstraint`.
+    fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
+        let scc = self.constraint_sccs.scc(r.to_region_vid());
+        binary_search_util::binary_search_slice(
+            &self.member_constraints_applied,
+            |applied| applied.member_region_scc,
+            &scc,
+        )
+    }
+
     /// Performs region inference and report errors if we see any
     /// unsatisfiable constraints. If this is a closure, returns the
     /// region requirements to propagate to our creator, if any.
@@ -428,11 +492,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // to store those. Otherwise, we'll pass in `None` to the
         // functions below, which will trigger them to report errors
         // eagerly.
-        let mut outlives_requirements = if infcx.tcx.is_closure(mir_def_id) {
-            Some(vec![])
-        } else {
-            None
-        };
+        let mut outlives_requirements =
+            if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
 
         self.check_type_tests(
             infcx,
@@ -451,16 +512,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             errors_buffer,
         );
 
+        self.check_member_constraints(infcx, mir_def_id, errors_buffer);
+
         let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
 
         if outlives_requirements.is_empty() {
             None
         } else {
             let num_external_vids = self.universal_regions.num_global_and_external_regions();
-            Some(ClosureRegionRequirements {
-                num_external_vids,
-                outlives_requirements,
-            })
+            Some(ClosureRegionRequirements { num_external_vids, outlives_requirements })
         }
     }
 
@@ -472,7 +532,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!("propagate_constraints()");
 
         debug!("propagate_constraints: constraints={:#?}", {
-            let mut constraints: Vec<_> = self.constraints.iter().collect();
+            let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
             constraints.sort();
             constraints
                 .into_iter()
@@ -488,8 +548,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         for scc_index in self.constraint_sccs.all_sccs() {
             self.propagate_constraint_sccs_if_new(scc_index, visited);
         }
+
+        // Sort the applied member constraints so we can binary search
+        // through them later.
+        self.member_constraints_applied.sort_by_key(|applied| applied.member_region_scc);
     }
 
+    /// Computes the value of the SCC `scc_a` if it has not already
+    /// been computed. The `visited` parameter is a bitset
     #[inline]
     fn propagate_constraint_sccs_if_new(
         &mut self,
@@ -501,6 +567,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
+    /// Computes the value of the SCC `scc_a`, which has not yet been
+    /// computed. This works by first computing all successors of the
+    /// SCC (if they haven't been computed already) and then unioning
+    /// together their elements.
     fn propagate_constraint_sccs_new(
         &mut self,
         scc_a: ConstraintSccIndex,
@@ -510,10 +580,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // Walk each SCC `B` such that `A: B`...
         for &scc_b in constraint_sccs.successors(scc_a) {
-            debug!(
-                "propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}",
-                scc_a, scc_b
-            );
+            debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
 
             // ...compute the value of `B`...
             self.propagate_constraint_sccs_if_new(scc_b, visited);
@@ -531,6 +598,16 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
         }
 
+        // Now take member constraints into account.
+        let member_constraints = self.member_constraints.clone();
+        for m_c_i in member_constraints.indices(scc_a) {
+            self.apply_member_constraint(
+                scc_a,
+                m_c_i,
+                member_constraints.choice_regions(m_c_i),
+            );
+        }
+
         debug!(
             "propagate_constraint_sccs: scc_a = {:?} has value {:?}",
             scc_a,
@@ -538,6 +615,167 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         );
     }
 
+    /// Invoked for each `R0 member of [R1..Rn]` constraint.
+    ///
+    /// `scc` is the SCC containing R0, and `choice_regions` are the
+    /// `R1..Rn` regions -- they are always known to be universal
+    /// regions (and if that's not true, we just don't attempt to
+    /// enforce the constraint).
+    ///
+    /// The current value of `scc` at the time the method is invoked
+    /// is considered a *lower bound*.  If possible, we will modify
+    /// the constraint to set it equal to one of the option regions.
+    /// If we make any changes, returns true, else false.
+    fn apply_member_constraint(
+        &mut self,
+        scc: ConstraintSccIndex,
+        member_constraint_index: NllMemberConstraintIndex,
+        choice_regions: &[ty::RegionVid],
+    ) -> bool {
+        debug!("apply_member_constraint(scc={:?}, choice_regions={:#?})", scc, choice_regions,);
+
+        if let Some(uh_oh) =
+            choice_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
+        {
+            // FIXME(#61773): This case can only occur with
+            // `impl_trait_in_bindings`, I believe, and we are just
+            // opting not to handle it for now. See #61773 for
+            // details.
+            bug!(
+                "member constraint for `{:?}` has an option region `{:?}` \
+                 that is not a universal region",
+                self.member_constraints[member_constraint_index].opaque_type_def_id,
+                uh_oh,
+            );
+        }
+
+        // Create a mutable vector of the options. We'll try to winnow
+        // them down.
+        let mut choice_regions: Vec<ty::RegionVid> = choice_regions.to_vec();
+
+        // The 'member region' in a member constraint is part of the
+        // hidden type, which must be in the root universe. Therefore,
+        // it cannot have any placeholders in its value.
+        assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
+        debug_assert!(
+            self.scc_values.placeholders_contained_in(scc).next().is_none(),
+            "scc {:?} in a member constraint has placeholder value: {:?}",
+            scc,
+            self.scc_values.region_value_str(scc),
+        );
+
+        // The existing value for `scc` is a lower-bound. This will
+        // consist of some set `{P} + {LB}` of points `{P}` and
+        // lower-bound free regions `{LB}`. As each choice region `O`
+        // is a free region, it will outlive the points. But we can
+        // only consider the option `O` if `O: LB`.
+        choice_regions.retain(|&o_r| {
+            self.scc_values
+                .universal_regions_outlived_by(scc)
+                .all(|lb| self.universal_region_relations.outlives(o_r, lb))
+        });
+        debug!("apply_member_constraint: after lb, choice_regions={:?}", choice_regions);
+
+        // Now find all the *upper bounds* -- that is, each UB is a
+        // free region that must outlive the member region `R0` (`UB:
+        // R0`). Therefore, we need only keep an option `O` if `UB: O`
+        // for all UB.
+        if choice_regions.len() > 1 {
+            let universal_region_relations = self.universal_region_relations.clone();
+            let rev_constraint_graph = self.rev_constraint_graph();
+            for ub in self.upper_bounds(scc, &rev_constraint_graph) {
+                debug!("apply_member_constraint: ub={:?}", ub);
+                choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r));
+            }
+            debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions);
+        }
+
+        // If we ruled everything out, we're done.
+        if choice_regions.is_empty() {
+            return false;
+        }
+
+        // Otherwise, we need to find the minimum remaining choice, if
+        // any, and take that.
+        debug!("apply_member_constraint: choice_regions remaining are {:#?}", choice_regions);
+        let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
+            let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
+            let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
+            if r1_outlives_r2 && r2_outlives_r1 {
+                Some(r1.min(r2))
+            } else if r1_outlives_r2 {
+                Some(r2)
+            } else if r2_outlives_r1 {
+                Some(r1)
+            } else {
+                None
+            }
+        };
+        let mut min_choice = choice_regions[0];
+        for &other_option in &choice_regions[1..] {
+            debug!(
+                "apply_member_constraint: min_choice={:?} other_option={:?}",
+                min_choice, other_option,
+            );
+            match min(min_choice, other_option) {
+                Some(m) => min_choice = m,
+                None => {
+                    debug!(
+                        "apply_member_constraint: {:?} and {:?} are incomparable; no min choice",
+                        min_choice, other_option,
+                    );
+                    return false;
+                }
+            }
+        }
+
+        let min_choice_scc = self.constraint_sccs.scc(min_choice);
+        debug!(
+            "apply_member_constraint: min_choice={:?} best_choice_scc={:?}",
+            min_choice,
+            min_choice_scc,
+        );
+        if self.scc_values.add_region(scc, min_choice_scc) {
+            self.member_constraints_applied.push(AppliedMemberConstraint {
+                member_region_scc: scc,
+                min_choice,
+                member_constraint_index,
+            });
+
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Compute and return the reverse SCC-based constraint graph (lazilly).
+    fn upper_bounds(
+        &'a mut self,
+        scc0: ConstraintSccIndex,
+        rev_constraint_graph: &'a VecGraph<ConstraintSccIndex>,
+    ) -> impl Iterator<Item = RegionVid> + 'a {
+        let scc_values = &self.scc_values;
+        let mut duplicates = FxHashSet::default();
+        rev_constraint_graph
+            .depth_first_search(scc0)
+            .skip(1)
+            .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1))
+            .filter(move |&r| duplicates.insert(r))
+    }
+
+    /// Compute and return the reverse SCC-based constraint graph (lazilly).
+    fn rev_constraint_graph(
+        &mut self,
+    ) -> Rc<VecGraph<ConstraintSccIndex>> {
+        if let Some(g) = &self.rev_constraint_graph {
+            return g.clone();
+        }
+
+        let rev_graph = Rc::new(self.constraint_sccs.reverse());
+        self.rev_constraint_graph = Some(rev_graph.clone());
+        rev_graph
+    }
+
     /// Returns `true` if all the elements in the value of `scc_b` are nameable
     /// in `scc_a`. Used during constraint propagation, and only once
     /// the value of `scc_b` has been computed.
@@ -554,9 +792,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Otherwise, we have to iterate over the universe elements in
         // B's value, and check whether all of them are nameable
         // from universe_a
-        self.scc_values
-            .placeholders_contained_in(scc_b)
-            .all(|p| universe_a.can_name(p.universe))
+        self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
     }
 
     /// Extend `scc` so that it can outlive some placeholder region
@@ -731,12 +967,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> bool {
         let tcx = infcx.tcx;
 
-        let TypeTest {
-            generic_kind,
-            lower_bound,
-            locations,
-            verify_bound: _,
-        } = type_test;
+        let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
 
         let generic_ty = generic_kind.to_ty(tcx);
         let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
@@ -809,7 +1040,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         ty: Ty<'tcx>,
     ) -> Option<ClosureOutlivesSubject<'tcx>> {
         let tcx = infcx.tcx;
-        let gcx = tcx.global_tcx();
 
         debug!("try_promote_type_test_subject(ty = {:?})", ty);
 
@@ -863,8 +1093,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         });
         debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
 
-        // `lift_to_global` will only fail if we failed to promote some region.
-        gcx.lift_to_global(&ty)?;
+        // `has_local_value` will only be true if we failed to promote some region.
+        if ty.has_local_value() {
+            return None;
+        }
 
         Some(ClosureOutlivesSubject::Ty(ty))
     }
@@ -885,11 +1117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// except that it converts further takes the non-local upper
     /// bound of `'y`, so that the final result is non-local.
     fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
-        debug!(
-            "non_local_universal_upper_bound(r={:?}={})",
-            r,
-            self.region_value_str(r)
-        );
+        debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
 
         let lub = self.universal_upper_bound(r);
 
@@ -897,10 +1125,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // creator.
         let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
 
-        debug!(
-            "non_local_universal_upper_bound: non_local_lub={:?}",
-            non_local_lub
-        );
+        debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
 
         non_local_lub
     }
@@ -920,11 +1145,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
     ///   a result `'y`.
     fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
-        debug!(
-            "universal_upper_bound(r={:?}={})",
-            r,
-            self.region_value_str(r)
-        );
+        debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
 
         // Find the smallest universal region that contains all other
         // universal regions within `region`.
@@ -949,10 +1170,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         lower_bound: RegionVid,
         verify_bound: &VerifyBound<'tcx>,
     ) -> bool {
-        debug!(
-            "eval_verify_bound(lower_bound={:?}, verify_bound={:?})",
-            lower_bound, verify_bound
-        );
+        debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
 
         match verify_bound {
             VerifyBound::IfEq(test_ty, verify_bound1) => {
@@ -961,7 +1179,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
             VerifyBound::OutlivedBy(r) => {
                 let r_vid = self.to_region_vid(r);
-                self.eval_outlives(body, r_vid, lower_bound)
+                self.eval_outlives(r_vid, lower_bound)
             }
 
             VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
@@ -1034,22 +1252,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         })
     }
 
-    // Evaluate whether `sup_region: sub_region @ point`.
-    fn eval_outlives(
-        &self,
-        _body: &Body<'tcx>,
-        sup_region: RegionVid,
-        sub_region: RegionVid,
-    ) -> bool {
+    // Evaluate whether `sup_region == sub_region`.
+    fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
+        self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
+    }
+
+    // Evaluate whether `sup_region: sub_region`.
+    fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
         debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
 
         debug!(
-            "eval_outlives: sup_region's value = {:?}",
+            "eval_outlives: sup_region's value = {:?} universal={:?}",
             self.region_value_str(sup_region),
+            self.universal_regions.is_universal_region(sup_region),
         );
         debug!(
-            "eval_outlives: sub_region's value = {:?}",
+            "eval_outlives: sub_region's value = {:?} universal={:?}",
             self.region_value_str(sub_region),
+            self.universal_regions.is_universal_region(sub_region),
         );
 
         let sub_region_scc = self.constraint_sccs.scc(sub_region);
@@ -1061,9 +1281,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // now). Therefore, the sup-region outlives the sub-region if,
         // for each universal region R1 in the sub-region, there
         // exists some region R2 in the sup-region that outlives R1.
-        let universal_outlives = self.scc_values
-            .universal_regions_outlived_by(sub_region_scc)
-            .all(|r1| {
+        let universal_outlives =
+            self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| {
                 self.scc_values
                     .universal_regions_outlived_by(sup_region_scc)
                     .any(|r2| self.universal_region_relations.outlives(r2, r1))
@@ -1081,8 +1300,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             return true;
         }
 
-        self.scc_values
-            .contains_points(sup_region_scc, sub_region_scc)
+        self.scc_values.contains_points(sup_region_scc, sub_region_scc)
     }
 
     /// Once regions have been propagated, this method is used to see
@@ -1164,12 +1382,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // Because this free region must be in the ROOT universe, we
         // know it cannot contain any bound universes.
         assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
-        debug_assert!(
-            self.scc_values
-                .placeholders_contained_in(longer_fr_scc)
-                .next()
-                .is_none()
-        );
+        debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
 
         // Only check all of the relations for the main representative of each
         // SCC, otherwise just check that we outlive said representative. This
@@ -1223,9 +1436,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         errors_buffer: &mut Vec<Diagnostic>,
     ) -> Option<ErrorReported> {
         // If it is known that `fr: o`, carry on.
-        if self.universal_region_relations
-            .outlives(longer_fr, shorter_fr)
-        {
+        if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
             return None;
         }
 
@@ -1239,9 +1450,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // We'll call it `fr-` -- it's ever so slightly smaller than
             // `longer_fr`.
 
-            if let Some(fr_minus) = self
-                .universal_region_relations
-                .non_local_lower_bound(longer_fr)
+            if let Some(fr_minus) = self.universal_region_relations.non_local_lower_bound(longer_fr)
             {
                 debug!("check_universal_region: fr_minus={:?}", fr_minus);
 
@@ -1251,12 +1460,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // Grow `shorter_fr` until we find some non-local regions. (We
                 // always will.)  We'll call them `shorter_fr+` -- they're ever
                 // so slightly larger than `shorter_fr`.
-                let shorter_fr_plus = self.universal_region_relations
-                    .non_local_upper_bounds(&shorter_fr);
-                debug!(
-                    "check_universal_region: shorter_fr_plus={:?}",
-                    shorter_fr_plus
-                );
+                let shorter_fr_plus =
+                    self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
+                debug!("check_universal_region: shorter_fr_plus={:?}", shorter_fr_plus);
                 for &&fr in &shorter_fr_plus {
                     // Push the constraint `fr-: shorter_fr+`
                     propagated_outlives_requirements.push(ClosureOutlivesRequirement {
@@ -1288,28 +1494,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         longer_fr: RegionVid,
         placeholder: ty::PlaceholderRegion,
     ) {
-        debug!(
-            "check_bound_universal_region(fr={:?}, placeholder={:?})",
-            longer_fr, placeholder,
-        );
+        debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,);
 
         let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
-        debug!(
-            "check_bound_universal_region: longer_fr_scc={:?}",
-            longer_fr_scc,
-        );
+        debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,);
 
         // If we have some bound universal region `'a`, then the only
         // elements it can contain is itself -- we don't know anything
         // else about it!
         let error_element = match {
-            self.scc_values
-                .elements_contained_in(longer_fr_scc)
-                .find(|element| match element {
-                    RegionElement::Location(_) => true,
-                    RegionElement::RootUniversalRegion(_) => true,
-                    RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
-                })
+            self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
+                RegionElement::Location(_) => true,
+                RegionElement::RootUniversalRegion(_) => true,
+                RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
+            })
         } {
             Some(v) => v,
             None => return,
@@ -1320,7 +1518,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let error_region = match error_element {
             RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
             RegionElement::RootUniversalRegion(r) => r,
-            RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
+            RegionElement::PlaceholderRegion(error_placeholder) => self
+                .definitions
                 .iter_enumerated()
                 .filter_map(|(r, definition)| match definition.origin {
                     NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
@@ -1338,12 +1537,50 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // the AST-based checker uses a more conservative check,
         // so to even see this error, one must pass in a special
         // flag.
-        let mut diag = infcx
-            .tcx
-            .sess
-            .struct_span_err(span, "higher-ranked subtype error");
+        let mut diag = infcx.tcx.sess.struct_span_err(span, "higher-ranked subtype error");
         diag.emit();
     }
+
+    fn check_member_constraints(
+        &self,
+        infcx: &InferCtxt<'_, 'tcx>,
+        mir_def_id: DefId,
+        errors_buffer: &mut Vec<Diagnostic>,
+    ) {
+        let member_constraints = self.member_constraints.clone();
+        for m_c_i in member_constraints.all_indices() {
+            debug!("check_member_constraint(m_c_i={:?})", m_c_i);
+            let m_c = &member_constraints[m_c_i];
+            let member_region_vid = m_c.member_region_vid;
+            debug!(
+                "check_member_constraint: member_region_vid={:?} with value {}",
+                member_region_vid,
+                self.region_value_str(member_region_vid),
+            );
+            let choice_regions = member_constraints.choice_regions(m_c_i);
+            debug!("check_member_constraint: choice_regions={:?}", choice_regions);
+
+            // Did the member region wind up equal to any of the option regions?
+            if let Some(o) = choice_regions.iter().find(|&&o_r| {
+                self.eval_equal(o_r, m_c.member_region_vid)
+            }) {
+                debug!("check_member_constraint: evaluated as equal to {:?}", o);
+                continue;
+            }
+
+            // If not, report an error.
+            let region_scope_tree = &infcx.tcx.region_scope_tree(mir_def_id);
+            let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+            opaque_types::unexpected_hidden_region_diagnostic(
+                infcx.tcx,
+                Some(region_scope_tree),
+                m_c.opaque_type_def_id,
+                m_c.hidden_ty,
+                member_region,
+            )
+            .buffer(errors_buffer);
+        }
+    }
 }
 
 impl<'tcx> RegionDefinition<'tcx> {
@@ -1357,11 +1594,7 @@ impl<'tcx> RegionDefinition<'tcx> {
             _ => NLLRegionVariableOrigin::Existential,
         };
 
-        Self {
-            origin,
-            universe,
-            external_name: None,
-        }
+        Self { origin, universe, external_name: None }
     }
 }
 
@@ -1371,7 +1604,7 @@ pub trait ClosureRegionRequirementsExt<'tcx> {
         tcx: TyCtxt<'tcx>,
         closure_def_id: DefId,
         closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryRegionConstraint<'tcx>>;
+    ) -> Vec<QueryOutlivesConstraint<'tcx>>;
 
     fn subst_closure_mapping<T>(
         &self,
@@ -1401,7 +1634,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
         tcx: TyCtxt<'tcx>,
         closure_def_id: DefId,
         closure_substs: SubstsRef<'tcx>,
-    ) -> Vec<QueryRegionConstraint<'tcx>> {
+    ) -> Vec<QueryOutlivesConstraint<'tcx>> {
         debug!(
             "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
             closure_def_id, closure_substs
@@ -1464,10 +1697,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
             if let ty::ReClosureBound(vid) = r {
                 closure_mapping[*vid]
             } else {
-                bug!(
-                    "subst_closure_mapping: encountered non-closure bound free region {:?}",
-                    r
-                )
+                bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r)
             }
         })
     }
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index cfd80cecca5..6f9f5707935 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -162,7 +162,7 @@ impl<N: Idx> LivenessValues<N> {
     }
 
     /// Iterate through each region that has a value in this set.
-    crate fn rows<'a>(&'a self) -> impl Iterator<Item = N> {
+    crate fn rows(&self) -> impl Iterator<Item=N> {
         self.points.rows()
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
index 77a4d2699ff..8de014522de 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
@@ -3,7 +3,8 @@ use crate::borrow_check::nll::region_infer::TypeTest;
 use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::borrow_check::nll::universal_regions::UniversalRegions;
 use crate::borrow_check::nll::ToRegionVid;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
+use rustc::infer::canonical::QueryOutlivesConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
@@ -49,13 +50,33 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
         }
     }
 
-    pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
-        for query_constraint in query_constraints {
+    pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
+        debug!("convert_all(query_constraints={:#?})", query_constraints);
+
+        let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
+
+        // Annoying: to invoke `self.to_region_vid`, we need access to
+        // `self.constraints`, but we also want to be mutating
+        // `self.member_constraints`. For now, just swap out the value
+        // we want and replace at the end.
+        let mut tmp = std::mem::replace(
+            &mut self.constraints.member_constraints,
+            Default::default(),
+        );
+        for member_constraint in member_constraints {
+            tmp.push_constraint(
+                member_constraint,
+                |r| self.to_region_vid(r),
+            );
+        }
+        self.constraints.member_constraints = tmp;
+
+        for query_constraint in outlives {
             self.convert(query_constraint);
         }
     }
 
-    pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
+    pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
         debug!("generate: constraints at: {:#?}", self.locations);
 
         // Extract out various useful fields we'll need below.
diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
index 1bb3acc28f0..d18a8e87453 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
@@ -2,7 +2,7 @@ use crate::borrow_check::nll::type_check::constraint_conversion;
 use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::borrow_check::nll::universal_regions::UniversalRegions;
 use crate::borrow_check::nll::ToRegionVid;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::free_region_map::FreeRegionRelations;
 use rustc::infer::region_constraints::GenericKind;
 use rustc::infer::InferCtxt;
@@ -287,7 +287,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
             self.relations.relate_universal_regions(fr, fr_fn_body);
         }
 
-        for data in constraint_sets {
+        for data in &constraint_sets {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 &self.universal_regions,
@@ -297,7 +297,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 Locations::All(DUMMY_SP),
                 ConstraintCategory::Internal,
                 &mut self.constraints,
-            ).convert_all(&data);
+            ).convert_all(data);
         }
 
         CreateResult {
@@ -311,7 +311,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
     /// either the return type of the MIR or one of its arguments. At
     /// the same time, compute and add any implied bounds that come
     /// from this local.
-    fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<Vec<QueryRegionConstraint<'tcx>>>> {
+    fn add_implied_bounds(&mut self, ty: Ty<'tcx>) -> Option<Rc<QueryRegionConstraints<'tcx>>> {
         debug!("add_implied_bounds(ty={:?})", ty);
         let (bounds, constraints) =
             self.param_env
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
index 3b138bc1262..4af78fa5e0f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs
@@ -1,5 +1,5 @@
 use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::ConstraintSet;
+use crate::borrow_check::nll::constraints::OutlivesConstraintSet;
 use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
 use crate::borrow_check::nll::region_infer::values::RegionValueElements;
 use crate::borrow_check::nll::universal_regions::UniversalRegions;
@@ -107,7 +107,7 @@ fn compute_live_locals(
 fn regions_that_outlive_free_regions(
     num_region_vars: usize,
     universal_regions: &UniversalRegions<'tcx>,
-    constraint_set: &ConstraintSet,
+    constraint_set: &OutlivesConstraintSet,
 ) -> FxHashSet<RegionVid> {
     // Build a graph of the outlives constraints thus far. This is
     // a reverse graph, so for each constraint `R1: R2` we have an
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 f1d568f0cf2..f160f658f55 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
@@ -6,7 +6,7 @@ use crate::borrow_check::nll::type_check::TypeChecker;
 use crate::dataflow::indexes::MovePathIndex;
 use crate::dataflow::move_paths::MoveData;
 use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Body};
 use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
 use rustc::traits::query::type_op::outlives::DropckOutlives;
@@ -88,7 +88,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
 
 struct DropData<'tcx> {
     dropck_result: DropckOutlivesResult<'tcx>,
-    region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>,
+    region_constraint_data: Option<Rc<QueryRegionConstraints<'tcx>>>,
 }
 
 struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
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 9409fefb6bd..cdbbe1d02bd 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -4,7 +4,8 @@
 
 use crate::borrow_check::borrow_set::BorrowSet;
 use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::constraints::{OutlivesConstraintSet, OutlivesConstraint};
+use crate::borrow_check::nll::member_constraints::MemberConstraintSet;
 use crate::borrow_check::nll::facts::AllFacts;
 use crate::borrow_check::nll::region_infer::values::LivenessValues;
 use crate::borrow_check::nll::region_infer::values::PlaceholderIndex;
@@ -23,7 +24,7 @@ use crate::dataflow::MaybeInitializedPlaces;
 use either::Either;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::infer::canonical::QueryRegionConstraint;
+use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -127,7 +128,8 @@ pub(crate) fn type_check<'tcx>(
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
         liveness_constraints: LivenessValues::new(elements.clone()),
-        outlives_constraints: ConstraintSet::default(),
+        outlives_constraints: OutlivesConstraintSet::default(),
+        member_constraints: MemberConstraintSet::default(),
         closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
     };
@@ -215,7 +217,7 @@ fn translate_outlives_facts(cx: &mut BorrowCheckContext<'_, '_>) {
         let location_table = cx.location_table;
         facts
             .outlives
-            .extend(cx.constraints.outlives_constraints.iter().flat_map(
+            .extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
                 |constraint: &OutlivesConstraint| {
                     if let Some(from_location) = constraint.locations.from_location() {
                         Either::Left(iter::once((
@@ -582,7 +584,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         );
 
         let locations = location.to_locations();
-        for constraint in constraints.iter() {
+        for constraint in constraints.outlives().iter() {
             let mut constraint = *constraint;
             constraint.locations = locations;
             if let ConstraintCategory::Return
@@ -834,6 +836,7 @@ struct TypeChecker<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     last_span: Span,
+    body: &'a Body<'tcx>,
     /// User type annotations are shared between the main MIR and the MIR of
     /// all of the promoted items.
     user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
@@ -884,7 +887,9 @@ crate struct MirTypeckRegionConstraints<'tcx> {
     /// hence it must report on their liveness constraints.
     crate liveness_constraints: LivenessValues<RegionVid>,
 
-    crate outlives_constraints: ConstraintSet,
+    crate outlives_constraints: OutlivesConstraintSet,
+
+    crate member_constraints: MemberConstraintSet<'tcx, RegionVid>,
 
     crate closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
@@ -992,6 +997,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             infcx,
             last_span: DUMMY_SP,
             mir_def_id,
+            body,
             user_type_annotations: &body.user_type_annotations,
             param_env,
             region_bound_pairs,
@@ -1093,7 +1099,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         &mut self,
         locations: Locations,
         category: ConstraintCategory,
-        data: &[QueryRegionConstraint<'tcx>],
+        data: &QueryRegionConstraints<'tcx>,
     ) {
         debug!(
             "push_region_constraints: constraints generated at {:?} are {:#?}",
@@ -1109,7 +1115,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             locations,
             category,
             &mut self.borrowck_context.constraints,
-        ).convert_all(&data);
+        ).convert_all(data);
     }
 
     /// Convenient wrapper around `relate_tys::relate_types` -- see
@@ -1229,6 +1235,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let infcx = self.infcx;
         let tcx = infcx.tcx;
         let param_env = self.param_env;
+        let body = self.body;
         debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id);
         let opaque_type_map = self.fully_perform_op(
             locations,
@@ -1244,6 +1251,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             dummy_body_id,
                             param_env,
                             &anon_ty,
+                            locations.span(body),
                         ));
                     debug!(
                         "eq_opaque_type_and_type: \
@@ -2508,10 +2516,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         location: Location,
     ) -> ty::InstantiatedPredicates<'tcx> {
         if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
-            let closure_constraints =
-                closure_region_requirements.apply_requirements(tcx, def_id, substs);
+            let closure_constraints = QueryRegionConstraints {
+                outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs),
+
+                // Presently, closures never propagate member
+                // constraints to their parents -- they are enforced
+                // locally.  This is largely a non-issue as member
+                // constraints only come from `-> impl Trait` and
+                // friends which don't appear (thus far...) in
+                // closures.
+                member_constraints: vec![],
+            };
 
             let bounds_mapping = closure_constraints
+                .outlives
                 .iter()
                 .enumerate()
                 .filter_map(|(idx, constraint)| {
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index aa2b177e54e..538ac6881d9 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -130,7 +130,7 @@ pub(super) fn is_active<'tcx>(
 
 /// Determines if a given borrow is borrowing local data
 /// This is called for all Yield statements on movable generators
-pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
+pub(super) fn borrow_of_local_data(place: &Place<'_>) -> bool {
     place.iterate(|place_base, place_projection| {
         match place_base {
             PlaceBase::Static(..) => return false,
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs
index 222ce6d1c96..f679a00035d 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir/build/expr/category.rs
@@ -31,7 +31,7 @@ pub enum RvalueFunc {
 /// Determines the category for a given expression. Note that scope
 /// and paren expressions have no category.
 impl Category {
-    pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option<Category> {
+    pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
         match *ek {
             ExprKind::Scope { .. } => None,
 
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index b1b5233fbc8..7125eb6850b 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -28,7 +28,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                     candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
-            let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
+            let match_pairs = mem::take(&mut candidate.match_pairs);
             let mut changed = false;
             for match_pair in match_pairs {
                 match self.simplify_match_pair(match_pair, candidate) {
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 95e2e52092a..528dfbef694 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -826,6 +826,6 @@ impl Test<'_> {
     }
 }
 
-fn is_switch_ty<'tcx>(ty: Ty<'tcx>) -> bool {
+fn is_switch_ty(ty: Ty<'_>) -> bool {
     ty.is_integral() || ty.is_char() || ty.is_bool()
 }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index ad970de466c..80a035d8287 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -22,7 +22,7 @@ use syntax_pos::Span;
 use super::lints;
 
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Body<'tcx> {
+pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -171,11 +171,11 @@ pub fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Body<'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
-fn liberated_closure_env_ty<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn liberated_closure_env_ty(
+    tcx: TyCtxt<'_>,
     closure_expr_id: hir::HirId,
     body_id: hir::BodyId,
-) -> Ty<'tcx> {
+) -> Ty<'_> {
     let closure_ty = tcx.body_tables(body_id).node_type(closure_expr_id);
 
     let (closure_def_id, closure_substs) = match closure_ty.sty {
@@ -485,7 +485,7 @@ macro_rules! unpack {
     };
 }
 
-fn should_abort_on_panic<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: DefId, abi: Abi) -> bool {
+fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
     // Not callable from C, so we can safely unwind through these
     if abi == Abi::Rust || abi == Abi::RustCall { return false; }
 
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 4d5a2ccf659..e95ef0caaaf 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -22,7 +22,7 @@ use syntax::source_map::{Span, DUMMY_SP};
 use crate::interpret::{self,
     PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
     RawConst, ConstValue,
-    InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpretCx, StackPopCleanup,
+    InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
     Allocation, AllocId, MemoryKind, Memory,
     snapshot, RefTracking, intern_const_alloc_recursive,
 };
@@ -34,7 +34,7 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
 /// Should be a power of two for performance reasons.
 const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
 
-/// The `InterpretCx` is only meant to be used to do field and index projections into constants for
+/// The `InterpCx` is only meant to be used to do field and index projections into constants for
 /// `simd_shuffle` and const patterns in match arms.
 ///
 /// The function containing the `match` that is currently being analyzed may have generic bounds
@@ -47,7 +47,7 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
 ) -> CompileTimeEvalContext<'mir, 'tcx> {
     debug!("mk_eval_cx: {:?}", param_env);
-    InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
+    InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default())
 }
 
 pub(crate) fn eval_promoted<'mir, 'tcx>(
@@ -303,7 +303,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
 }
 
 crate type CompileTimeEvalContext<'mir, 'tcx> =
-    InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
+    InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
 
 impl interpret::MayLeak for ! {
     #[inline(always)]
@@ -326,12 +326,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     const STATIC_KIND: Option<!> = None; // no copying of statics allowed
 
     #[inline(always)]
-    fn enforce_validity(_ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool {
+    fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         false // for now, we don't enforce validity
     }
 
     fn find_fn(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
         dest: Option<PlaceTy<'tcx>>,
@@ -371,7 +371,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     fn call_intrinsic(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx>],
         dest: PlaceTy<'tcx>,
@@ -387,7 +387,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     fn ptr_op(
-        _ecx: &InterpretCx<'mir, 'tcx, Self>,
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
         _left: ImmTy<'tcx>,
         _right: ImmTy<'tcx>,
@@ -424,7 +424,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     fn box_alloc(
-        _ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _dest: PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
         Err(
@@ -432,7 +432,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         )
     }
 
-    fn before_terminator(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+    fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         {
             let steps = &mut ecx.machine.steps_since_detector_enabled;
 
@@ -457,13 +457,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     }
 
     #[inline(always)]
-    fn stack_push(_ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+    fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         Ok(())
     }
 
     /// Called immediately before a stack frame gets popped.
     #[inline(always)]
-    fn stack_pop(_ecx: &mut InterpretCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
+    fn stack_pop(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _extra: ()) -> InterpResult<'tcx> {
         Ok(())
     }
 }
@@ -508,7 +508,7 @@ pub fn const_variant_index<'tcx>(
 }
 
 pub fn error_to_const_error<'mir, 'tcx>(
-    ecx: &InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+    ecx: &InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
     mut error: InterpErrorInfo<'tcx>,
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
@@ -632,7 +632,7 @@ pub fn const_eval_raw_provider<'tcx>(
     }
 
     let span = tcx.def_span(cid.instance.def_id());
-    let mut ecx = InterpretCx::new(
+    let mut ecx = InterpCx::new(
         tcx.at(span),
         key.param_env,
         CompileTimeInterpreter::new(),
diff --git a/src/librustc_mir/dataflow/at_location.rs b/src/librustc_mir/dataflow/at_location.rs
index 7735528d8f8..f0014602e2d 100644
--- a/src/librustc_mir/dataflow/at_location.rs
+++ b/src/librustc_mir/dataflow/at_location.rs
@@ -8,6 +8,7 @@ use crate::dataflow::{BitDenotation, DataflowResults, GenKillSet};
 use crate::dataflow::move_paths::{HasMoveData, MovePathIndex};
 
 use std::iter;
+use std::borrow::Borrow;
 
 /// A trait for "cartesian products" of multiple FlowAtLocation.
 ///
@@ -60,18 +61,20 @@ pub trait FlowsAtLocation {
 /// (e.g., via `reconstruct_statement_effect` and
 /// `reconstruct_terminator_effect`; don't forget to call
 /// `apply_local_effect`).
-pub struct FlowAtLocation<'tcx, BD>
+pub struct FlowAtLocation<'tcx, BD, DR = DataflowResults<'tcx, BD>>
 where
     BD: BitDenotation<'tcx>,
+    DR: Borrow<DataflowResults<'tcx, BD>>,
 {
-    base_results: DataflowResults<'tcx, BD>,
+    base_results: DR,
     curr_state: BitSet<BD::Idx>,
     stmt_trans: GenKillSet<BD::Idx>,
 }
 
-impl<'tcx, BD> FlowAtLocation<'tcx, BD>
+impl<'tcx, BD, DR> FlowAtLocation<'tcx, BD, DR>
 where
     BD: BitDenotation<'tcx>,
+    DR: Borrow<DataflowResults<'tcx, BD>>,
 {
     /// Iterate over each bit set in the current state.
     pub fn each_state_bit<F>(&self, f: F)
@@ -91,8 +94,8 @@ where
         self.stmt_trans.gen_set.iter().for_each(f)
     }
 
-    pub fn new(results: DataflowResults<'tcx, BD>) -> Self {
-        let bits_per_block = results.sets().bits_per_block();
+    pub fn new(results: DR) -> Self {
+        let bits_per_block = results.borrow().sets().bits_per_block();
         let curr_state = BitSet::new_empty(bits_per_block);
         let stmt_trans = GenKillSet::from_elem(HybridBitSet::new_empty(bits_per_block));
         FlowAtLocation {
@@ -104,7 +107,7 @@ where
 
     /// Access the underlying operator.
     pub fn operator(&self) -> &BD {
-        self.base_results.operator()
+        self.base_results.borrow().operator()
     }
 
     pub fn contains(&self, x: BD::Idx) -> bool {
@@ -134,27 +137,31 @@ where
     }
 }
 
-impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
-    where BD: BitDenotation<'tcx>
+impl<'tcx, BD, DR> FlowsAtLocation for FlowAtLocation<'tcx, BD, DR>
+where
+    BD: BitDenotation<'tcx>,
+    DR: Borrow<DataflowResults<'tcx, BD>>,
 {
     fn reset_to_entry_of(&mut self, bb: BasicBlock) {
-        self.curr_state.overwrite(self.base_results.sets().entry_set_for(bb.index()));
+        self.curr_state.overwrite(self.base_results.borrow().sets().entry_set_for(bb.index()));
     }
 
     fn reset_to_exit_of(&mut self, bb: BasicBlock) {
         self.reset_to_entry_of(bb);
-        let trans = self.base_results.sets().trans_for(bb.index());
+        let trans = self.base_results.borrow().sets().trans_for(bb.index());
         trans.apply(&mut self.curr_state)
     }
 
     fn reconstruct_statement_effect(&mut self, loc: Location) {
         self.stmt_trans.clear();
         self.base_results
+            .borrow()
             .operator()
             .before_statement_effect(&mut self.stmt_trans, loc);
         self.stmt_trans.apply(&mut self.curr_state);
 
         self.base_results
+            .borrow()
             .operator()
             .statement_effect(&mut self.stmt_trans, loc);
     }
@@ -162,11 +169,13 @@ impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
     fn reconstruct_terminator_effect(&mut self, loc: Location) {
         self.stmt_trans.clear();
         self.base_results
+            .borrow()
             .operator()
             .before_terminator_effect(&mut self.stmt_trans, loc);
         self.stmt_trans.apply(&mut self.curr_state);
 
         self.base_results
+            .borrow()
             .operator()
             .terminator_effect(&mut self.stmt_trans, loc);
     }
@@ -177,9 +186,10 @@ impl<'tcx, BD> FlowsAtLocation for FlowAtLocation<'tcx, BD>
 }
 
 
-impl<'tcx, T> FlowAtLocation<'tcx, T>
+impl<'tcx, T, DR> FlowAtLocation<'tcx, T, DR>
 where
     T: HasMoveData<'tcx> + BitDenotation<'tcx, Idx = MovePathIndex>,
+    DR: Borrow<DataflowResults<'tcx, T>>,
 {
     pub fn has_any_child_of(&self, mpi: T::Idx) -> Option<T::Idx> {
         // We process `mpi` before the loop below, for two reasons:
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
index 0f7f37f2db8..d94ebdbae24 100644
--- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs
+++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
@@ -92,7 +92,7 @@ struct BorrowedLocalsVisitor<'gk> {
     trans: &'gk mut GenKillSet<Local>,
 }
 
-fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
+fn find_local(place: &Place<'_>) -> Option<Local> {
     place.iterate(|place_base, place_projection| {
         for proj in place_projection {
             if proj.elem == ProjectionElem::Deref {
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
index d2003993d45..7fa950cb98d 100644
--- a/src/librustc_mir/dataflow/impls/storage_liveness.rs
+++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs
@@ -1,7 +1,13 @@
 pub use super::*;
 
 use rustc::mir::*;
+use rustc::mir::visit::{
+    PlaceContext, Visitor, NonMutatingUseContext,
+};
+use std::cell::RefCell;
 use crate::dataflow::BitDenotation;
+use crate::dataflow::HaveBeenBorrowedLocals;
+use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor};
 
 #[derive(Copy, Clone)]
 pub struct MaybeStorageLive<'a, 'tcx> {
@@ -27,7 +33,9 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
     }
 
     fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
-        // Nothing is live on function entry
+        // Nothing is live on function entry (generators only have a self
+        // argument, and we don't care about that)
+        assert_eq!(1, self.body.arg_count);
     }
 
     fn statement_effect(&self,
@@ -63,3 +71,123 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
     /// bottom = dead
     const BOTTOM_VALUE: bool = false;
 }
+
+/// Dataflow analysis that determines whether each local requires storage at a
+/// given location; i.e. whether its storage can go away without being observed.
+pub struct RequiresStorage<'mir, 'tcx> {
+    body: &'mir Body<'tcx>,
+    borrowed_locals:
+        RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
+}
+
+impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
+    pub fn new(
+        body: &'mir Body<'tcx>,
+        borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
+    ) -> Self {
+        RequiresStorage {
+            body,
+            borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, body)),
+        }
+    }
+
+    pub fn body(&self) -> &Body<'tcx> {
+        self.body
+    }
+}
+
+impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
+    type Idx = Local;
+    fn name() -> &'static str { "requires_storage" }
+    fn bits_per_block(&self) -> usize {
+        self.body.local_decls.len()
+    }
+
+    fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
+        // Nothing is live on function entry (generators only have a self
+        // argument, and we don't care about that)
+        assert_eq!(1, self.body.arg_count);
+    }
+
+    fn statement_effect(&self,
+                        sets: &mut GenKillSet<Local>,
+                        loc: Location) {
+        self.check_for_move(sets, loc);
+        self.check_for_borrow(sets, loc);
+
+        let stmt = &self.body[loc.block].statements[loc.statement_index];
+        match stmt.kind {
+            StatementKind::StorageLive(l) => sets.gen(l),
+            StatementKind::StorageDead(l) => sets.kill(l),
+            StatementKind::Assign(ref place, _)
+            | StatementKind::SetDiscriminant { ref place, .. } => {
+                place.base_local().map(|l| sets.gen(l));
+            }
+            StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
+                for p in &**outputs {
+                    p.base_local().map(|l| sets.gen(l));
+                }
+            }
+            _ => (),
+        }
+    }
+
+    fn terminator_effect(&self,
+                         sets: &mut GenKillSet<Local>,
+                         loc: Location) {
+        self.check_for_move(sets, loc);
+        self.check_for_borrow(sets, loc);
+    }
+
+    fn propagate_call_return(
+        &self,
+        in_out: &mut BitSet<Local>,
+        _call_bb: mir::BasicBlock,
+        _dest_bb: mir::BasicBlock,
+        dest_place: &mir::Place<'tcx>,
+    ) {
+        dest_place.base_local().map(|l| in_out.insert(l));
+    }
+}
+
+impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
+    /// Kill locals that are fully moved and have not been borrowed.
+    fn check_for_move(&self, sets: &mut GenKillSet<Local>, loc: Location) {
+        let mut visitor = MoveVisitor {
+            sets,
+            borrowed_locals: &self.borrowed_locals,
+        };
+        visitor.visit_location(self.body, loc);
+    }
+
+    /// Gen locals that are newly borrowed. This includes borrowing any part of
+    /// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
+    fn check_for_borrow(&self, sets: &mut GenKillSet<Local>, loc: Location) {
+        let mut borrowed_locals = self.borrowed_locals.borrow_mut();
+        borrowed_locals.seek(loc);
+        borrowed_locals.each_gen_bit(|l| sets.gen(l));
+    }
+}
+
+impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
+    /// bottom = dead
+    const BOTTOM_VALUE: bool = false;
+}
+
+struct MoveVisitor<'a, 'mir, 'tcx> {
+    borrowed_locals:
+        &'a RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
+    sets: &'a mut GenKillSet<Local>,
+}
+
+impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
+    fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
+        if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
+            let mut borrowed_locals = self.borrowed_locals.borrow_mut();
+            borrowed_locals.seek(loc);
+            if !borrowed_locals.contains(*local) {
+                self.sets.kill(*local);
+            }
+        }
+    }
+}
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 80f65a9c8d0..5433a9013aa 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -17,7 +17,7 @@ use std::io;
 use std::path::PathBuf;
 use std::usize;
 
-pub use self::impls::{MaybeStorageLive};
+pub use self::impls::{MaybeStorageLive, RequiresStorage};
 pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 pub use self::impls::DefinitelyInitializedPlaces;
 pub use self::impls::EverInitializedPlaces;
@@ -228,9 +228,25 @@ where
     BD: BitDenotation<'tcx>,
 {
     fn walk_cfg(&mut self, in_out: &mut BitSet<BD::Idx>) {
-        let mut dirty_queue: WorkQueue<mir::BasicBlock> =
-            WorkQueue::with_all(self.builder.body.basic_blocks().len());
         let body = self.builder.body;
+
+        // Initialize the dirty queue in reverse post-order. This makes it more likely that the
+        // entry state for each basic block will have the effects of its predecessors applied
+        // before it is processed. In fact, for CFGs without back edges, this guarantees that
+        // dataflow will converge in exactly `N` iterations, where `N` is the number of basic
+        // blocks.
+        let mut dirty_queue: WorkQueue<mir::BasicBlock> =
+            WorkQueue::with_none(body.basic_blocks().len());
+        for (bb, _) in traversal::reverse_postorder(body) {
+            dirty_queue.insert(bb);
+        }
+
+        // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will
+        // be processed after the ones added above.
+        for bb in body.basic_blocks().indices() {
+            dirty_queue.insert(bb);
+        }
+
         while let Some(bb) = dirty_queue.pop() {
             let (on_entry, trans) = self.builder.flow_state.sets.get_mut(bb.index());
             debug_assert!(in_out.words().len() == on_entry.words().len());
@@ -344,6 +360,99 @@ pub(crate) trait DataflowResultsConsumer<'a, 'tcx: 'a> {
     fn body(&self) -> &'a Body<'tcx>;
 }
 
+/// Allows iterating dataflow results in a flexible and reasonably fast way.
+pub struct DataflowResultsCursor<'mir, 'tcx, BD, DR = DataflowResults<'tcx, BD>>
+where
+    BD: BitDenotation<'tcx>,
+    DR: Borrow<DataflowResults<'tcx, BD>>,
+{
+    flow_state: FlowAtLocation<'tcx, BD, DR>,
+
+    // The statement (or terminator) whose effect has been reconstructed in
+    // flow_state.
+    curr_loc: Option<Location>,
+
+    body: &'mir Body<'tcx>,
+}
+
+pub type DataflowResultsRefCursor<'mir, 'tcx, BD> =
+    DataflowResultsCursor<'mir, 'tcx, BD, &'mir DataflowResults<'tcx, BD>>;
+
+impl<'mir, 'tcx, BD, DR> DataflowResultsCursor<'mir, 'tcx, BD, DR>
+where
+    BD: BitDenotation<'tcx>,
+    DR: Borrow<DataflowResults<'tcx, BD>>,
+{
+    pub fn new(result: DR, body: &'mir Body<'tcx>) -> Self {
+        DataflowResultsCursor {
+            flow_state: FlowAtLocation::new(result),
+            curr_loc: None,
+            body,
+        }
+    }
+
+    /// Seek to the given location in MIR. This method is fast if you are
+    /// traversing your MIR statements in order.
+    ///
+    /// After calling `seek`, the current state will reflect all effects up to
+    /// and including the `before_statement_effect` of the statement at location
+    /// `loc`. The `statement_effect` of the statement at `loc` will be
+    /// available as the current effect (see e.g. `each_gen_bit`).
+    ///
+    /// If `loc.statement_index` equals the number of statements in the block,
+    /// we will reconstruct the terminator effect in the same way as described
+    /// above.
+    pub fn seek(&mut self, loc: Location) {
+        if self.curr_loc.map(|cur| loc == cur).unwrap_or(false) {
+            return;
+        }
+
+        let start_index;
+        let should_reset = match self.curr_loc {
+            None => true,
+            Some(cur)
+                if loc.block != cur.block || loc.statement_index < cur.statement_index => true,
+            _ => false,
+        };
+        if should_reset {
+            self.flow_state.reset_to_entry_of(loc.block);
+            start_index = 0;
+        } else {
+            let curr_loc = self.curr_loc.unwrap();
+            start_index = curr_loc.statement_index;
+            // Apply the effect from the last seek to the current state.
+            self.flow_state.apply_local_effect(curr_loc);
+        }
+
+        for stmt in start_index..loc.statement_index {
+            let mut stmt_loc = loc;
+            stmt_loc.statement_index = stmt;
+            self.flow_state.reconstruct_statement_effect(stmt_loc);
+            self.flow_state.apply_local_effect(stmt_loc);
+        }
+
+        if loc.statement_index == self.body[loc.block].statements.len() {
+            self.flow_state.reconstruct_terminator_effect(loc);
+        } else {
+            self.flow_state.reconstruct_statement_effect(loc);
+        }
+        self.curr_loc = Some(loc);
+    }
+
+    /// Return whether the current state contains bit `x`.
+    pub fn contains(&self, x: BD::Idx) -> bool {
+        self.flow_state.contains(x)
+    }
+
+    /// Iterate over each `gen` bit in the current effect (invoke `seek` first).
+    pub fn each_gen_bit<F>(&self, f: F)
+    where
+        F: FnMut(BD::Idx),
+    {
+        self.flow_state.each_gen_bit(f)
+    }
+}
+
 pub fn state_for_location<'tcx, T: BitDenotation<'tcx>>(loc: Location,
                                                         analysis: &T,
                                                         result: &DataflowResults<'tcx, T>,
diff --git a/src/librustc_mir/hair/cx/to_ref.rs b/src/librustc_mir/hair/cx/to_ref.rs
index 946d66fc91d..c365cc2ad85 100644
--- a/src/librustc_mir/hair/cx/to_ref.rs
+++ b/src/librustc_mir/hair/cx/to_ref.rs
@@ -1,7 +1,7 @@
 use crate::hair::*;
 
 use rustc::hir;
-use syntax::ptr::P;
+use rustc::hir::ptr::P;
 
 pub trait ToRef {
     type Output;
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index fc2951895f3..d356194c003 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -835,7 +835,7 @@ impl<'tcx> IntRange<'tcx> {
     fn from_ctor(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> Option<IntRange<'tcx>> {
         // Floating-point ranges are permitted and we don't want
         // to consider them when constructing integer ranges.
-        fn is_integral<'tcx>(ty: Ty<'tcx>) -> bool {
+        fn is_integral(ty: Ty<'_>) -> bool {
             match ty.sty {
                 ty::Char | ty::Int(_) | ty::Uint(_) => true,
                 _ => false,
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index ed850379af6..915ce9f20d0 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -18,15 +18,15 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc::hir::def::*;
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::hir::ptr::P;
 use rustc::hir::{self, Pat, PatKind};
 
 use smallvec::smallvec;
 use std::slice;
 
-use syntax::ptr::P;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 
-pub(crate) fn check_match<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
     let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) {
         tcx.hir().body_owned_by(id)
     } else {
@@ -43,7 +43,7 @@ pub(crate) fn check_match<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
     }.visit_body(tcx.hir().body(body_id));
 }
 
-fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> {
+fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> {
     struct_span_err!(sess, sp, E0004, "{}", &error_message)
 }
 
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index cf597ce0b63..6ba2f587768 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -20,13 +20,13 @@ use rustc::ty::layout::{VariantIdx, Size};
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+use rustc::hir::ptr::P;
 
 use rustc_data_structures::indexed_vec::Idx;
 
 use std::cmp::Ordering;
 use std::fmt;
 use syntax::ast;
-use syntax::ptr::P;
 use syntax::symbol::sym;
 use syntax_pos::Span;
 
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index fbacdf6cd93..d61fb87336c 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -1,7 +1,7 @@
 use rustc::ty::{self, Ty, TypeAndMut};
 use rustc::ty::layout::{self, TyLayout, Size};
 use rustc::ty::adjustment::{PointerCast};
-use syntax::ast::{FloatTy, IntTy, UintTy};
+use syntax::ast::FloatTy;
 use syntax::symbol::sym;
 
 use rustc_apfloat::ieee::{Single, Double};
@@ -11,9 +11,9 @@ use rustc::mir::interpret::{
 };
 use rustc::mir::CastKind;
 
-use super::{InterpretCx, Machine, PlaceTy, OpTy, Immediate};
+use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate};
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
         match ty.sty {
             ty::RawPtr(ty::TypeAndMut { ty, .. }) |
@@ -151,7 +151,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
                     "Unexpected cast from type {:?}", src_layout.ty
                 );
                 match val.to_bits_or_ptr(src_layout.size, self) {
-                    Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
+                    Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
                     Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
                 }
             }
@@ -239,17 +239,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
     fn cast_from_ptr(
         &self,
         ptr: Pointer<M::PointerTag>,
-        ty: Ty<'tcx>
+        src_layout: TyLayout<'tcx>,
+        dest_layout: TyLayout<'tcx>,
     ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
-        match ty.sty {
+
+        match dest_layout.ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
             // no need to support it here.
-            RawPtr(_) |
-            Int(IntTy::Isize) |
-            Uint(UintTy::Usize) => Ok(ptr.into()),
-            Int(_) | Uint(_) => err!(ReadPointerAsBytes),
-            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
+            RawPtr(_) => Ok(ptr.into()),
+            Int(_) | Uint(_) => {
+                let size = self.memory.pointer_size();
+
+                match self.force_bits(Scalar::Ptr(ptr), size) {
+                    Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout),
+                    Err(_) if dest_layout.size == size => Ok(ptr.into()),
+                    Err(e) => Err(e),
+                }
+            }
+            _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty)
         }
     }
 
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4c4330ffb26..fd5290ee040 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -26,7 +26,7 @@ use super::{
     Memory, Machine
 };
 
-pub struct InterpretCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
+pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// Stores the `Machine` instance.
     pub machine: M,
 
@@ -158,14 +158,14 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
     #[inline]
     fn data_layout(&self) -> &layout::TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
-impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpCx<'mir, 'tcx, M>
 where
     M: Machine<'mir, 'tcx>,
 {
@@ -175,7 +175,7 @@ where
     }
 }
 
-impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpCx<'mir, 'tcx, M>
 where
     M: Machine<'mir, 'tcx>,
 {
@@ -184,7 +184,7 @@ where
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
     type Ty = Ty<'tcx>;
     type TyLayout = InterpResult<'tcx, TyLayout<'tcx>>;
 
@@ -195,14 +195,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpretCx<'mir, 'tcx, M>
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn new(
         tcx: TyCtxtAt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         machine: M,
         memory_extra: M::MemoryExtra,
     ) -> Self {
-        InterpretCx {
+        InterpCx {
             machine,
             tcx,
             param_env,
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index beb50493071..cf36c10a614 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -11,7 +11,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    Machine, PlaceTy, OpTy, InterpretCx, Immediate,
+    Machine, PlaceTy, OpTy, InterpCx, Immediate,
 };
 
 mod type_name;
@@ -39,7 +39,7 @@ fn numeric_intrinsic<'tcx, Tag>(
     Ok(Scalar::from_uint(bits_out, size))
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Returns `true` if emulation happened.
     pub fn emulate_intrinsic(
         &mut self,
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index a3956e12300..ff560360f0a 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -11,7 +11,7 @@ use rustc::ty::{self, query::TyCtxtAt};
 
 use super::{
     Allocation, AllocId, InterpResult, Scalar, AllocationExtra,
-    InterpretCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory
+    InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory
 };
 
 /// Whether this kind of memory is allowed to leak
@@ -95,11 +95,11 @@ pub trait Machine<'mir, 'tcx>: Sized {
     const STATIC_KIND: Option<Self::MemoryKinds>;
 
     /// Whether to enforce the validity invariant
-    fn enforce_validity(ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool;
+    fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
 
     /// Called before a basic block terminator is executed.
     /// You can use this to detect endlessly running programs.
-    fn before_terminator(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
+    fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
 
     /// Entry point to all function calls.
     ///
@@ -112,7 +112,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
     /// was used.
     fn find_fn(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::PointerTag>],
         dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
@@ -122,7 +122,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Directly process an intrinsic without pushing a stack frame.
     /// If this returns successfully, the engine will take care of jumping to the next block.
     fn call_intrinsic(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         args: &[OpTy<'tcx, Self::PointerTag>],
         dest: PlaceTy<'tcx, Self::PointerTag>,
@@ -145,7 +145,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     ///
     /// Returns a (value, overflowed) pair if the operation succeeded
     fn ptr_op(
-        ecx: &InterpretCx<'mir, 'tcx, Self>,
+        ecx: &InterpCx<'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
         left: ImmTy<'tcx, Self::PointerTag>,
         right: ImmTy<'tcx, Self::PointerTag>,
@@ -153,7 +153,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
 
     /// Heap allocations via the `box` keyword.
     fn box_alloc(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> InterpResult<'tcx>;
 
@@ -193,7 +193,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Executes a retagging operation
     #[inline]
     fn retag(
-        _ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _kind: mir::RetagKind,
         _place: PlaceTy<'tcx, Self::PointerTag>,
     ) -> InterpResult<'tcx> {
@@ -201,11 +201,11 @@ pub trait Machine<'mir, 'tcx>: Sized {
     }
 
     /// Called immediately before a new stack frame got pushed
-    fn stack_push(ecx: &mut InterpretCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
+    fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
 
     /// Called immediately after a stack frame gets popped
     fn stack_pop(
-        ecx: &mut InterpretCx<'mir, 'tcx, Self>,
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
         extra: Self::FrameExtra,
     ) -> InterpResult<'tcx>;
 
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index c06fdccf6ca..f5d91259533 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -158,8 +158,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     pub fn reallocate(
         &mut self,
         ptr: Pointer<M::PointerTag>,
-        old_size: Size,
-        old_align: Align,
+        old_size_and_align: Option<(Size, Align)>,
         new_size: Size,
         new_align: Align,
         kind: MemoryKind<M::MemoryKinds>,
@@ -171,15 +170,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
         // This happens so rarely, the perf advantage is outweighed by the maintenance cost.
         let new_ptr = self.allocate(new_size, new_align, kind);
+        let old_size = match old_size_and_align {
+            Some((size, _align)) => size,
+            None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64),
+        };
         self.copy(
             ptr.into(),
-            old_align,
+            Align::from_bytes(1).unwrap(), // old_align anyway gets checked below by `deallocate`
             new_ptr.into(),
             new_align,
             old_size.min(new_size),
             /*nonoverlapping*/ true,
         )?;
-        self.deallocate(ptr, Some((old_size, old_align)), kind)?;
+        self.deallocate(ptr, old_size_and_align, kind)?;
 
         Ok(new_ptr)
     }
@@ -198,7 +201,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     pub fn deallocate(
         &mut self,
         ptr: Pointer<M::PointerTag>,
-        size_and_align: Option<(Size, Align)>,
+        old_size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> InterpResult<'tcx> {
         trace!("deallocating: {}", ptr.alloc_id);
@@ -232,7 +235,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 format!("{:?}", kind),
             ));
         }
-        if let Some((size, align)) = size_and_align {
+        if let Some((size, align)) = old_size_and_align {
             if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
                 let bytes = Size::from_bytes(alloc.bytes.len() as u64);
                 return err!(IncorrectAllocationInformation(size,
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 259bd6af0d5..2b20f9df538 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -19,7 +19,7 @@ mod intern;
 pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
 pub use self::eval_context::{
-    InterpretCx, Frame, StackPopCleanup, LocalState, LocalValue,
+    InterpCx, Frame, StackPopCleanup, LocalState, LocalValue,
 };
 
 pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index c72078fa89c..68c9047f7b7 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -15,7 +15,7 @@ use rustc::mir::interpret::{
     sign_extend, truncate,
 };
 use super::{
-    InterpretCx, Machine,
+    InterpCx, Machine,
     MemPlace, MPlaceTy, PlaceTy, Place,
 };
 pub use rustc::mir::interpret::ScalarMaybeUndef;
@@ -213,7 +213,7 @@ pub(super) fn from_known_layout<'tcx>(
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
     /// Returns `None` if the layout does not permit loading this as a value.
     fn try_read_immediate_from_mplace(
diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs
index 029a440f34e..20180c9cba5 100644
--- a/src/librustc_mir/interpret/operator.rs
+++ b/src/librustc_mir/interpret/operator.rs
@@ -4,10 +4,10 @@ use syntax::ast::FloatTy;
 use rustc_apfloat::Float;
 use rustc::mir::interpret::{InterpResult, Scalar};
 
-use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy};
+use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
 
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Applies the binary operation `op` to the two operands and writes a tuple of the result
     /// and a boolean signifying the potential overflow to the destination.
     pub fn binop_with_overflow(
@@ -36,7 +36,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn binary_char_op(
         &self,
         bin_op: mir::BinOp,
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 1351b5bb8bd..4f3727fbd8d 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -13,7 +13,7 @@ use rustc::ty::TypeFoldable;
 
 use super::{
     GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
-    InterpretCx, Machine, AllocMap, AllocationExtra,
+    InterpCx, Machine, AllocMap, AllocationExtra,
     RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
 };
 
@@ -290,7 +290,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
 }
 
 // separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
-impl<'mir, 'tcx, Tag, M> InterpretCx<'mir, 'tcx, M>
+impl<'mir, 'tcx, Tag, M> InterpCx<'mir, 'tcx, M>
 where
     // FIXME: Working around https://github.com/rust-lang/rust/issues/54385
     Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static,
@@ -583,7 +583,7 @@ where
                 // global table but not in its local memory: It calls back into tcx through
                 // a query, triggering the CTFE machinery to actually turn this lazy reference
                 // into a bunch of bytes.  IOW, statics are evaluated with CTFE even when
-                // this InterpretCx uses another Machine (e.g., in miri).  This is what we
+                // this InterpCx uses another Machine (e.g., in miri).  This is what we
                 // want!  This way, computing statics works consistently between codegen
                 // and miri: They use the same query to eventually obtain a `ty::Const`
                 // and use that for further computation.
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 2f99973b90d..dc5302eb18f 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -1,4 +1,4 @@
-//! This module contains the `InterpretCx` methods for executing a single step of the interpreter.
+//! This module contains the `InterpCx` methods for executing a single step of the interpreter.
 //!
 //! The main entry point is the `step` method.
 
@@ -6,7 +6,7 @@ use rustc::mir;
 use rustc::ty::layout::LayoutOf;
 use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic};
 
-use super::{InterpretCx, Machine};
+use super::{InterpCx, Machine};
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
 /// same type as the result.
@@ -35,7 +35,7 @@ fn binop_right_homogeneous(op: mir::BinOp) -> bool {
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn run(&mut self) -> InterpResult<'tcx> {
         while self.step()? {}
         Ok(())
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 13baf245d10..d6f3de02ec9 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -8,10 +8,10 @@ use rustc_target::spec::abi::Abi;
 
 use rustc::mir::interpret::{InterpResult, PointerArithmetic, InterpError, Scalar};
 use super::{
-    InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
+    InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
 };
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     #[inline]
     pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> InterpResult<'tcx> {
         if let Some(target) = target {
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 5d2f268d266..27d12751422 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -2,9 +2,9 @@ use rustc::ty::{self, Ty, Instance};
 use rustc::ty::layout::{Size, Align, LayoutOf};
 use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic};
 
-use super::{InterpretCx, InterpError, Machine, MemoryKind};
+use super::{InterpCx, InterpError, Machine, MemoryKind};
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
     /// objects.
     ///
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index b2a159fef59..374f42261bf 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -13,7 +13,7 @@ use rustc::mir::interpret::{
 use std::hash::Hash;
 
 use super::{
-    OpTy, Machine, InterpretCx, ValueVisitor, MPlaceTy,
+    OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy,
 };
 
 macro_rules! validation_failure {
@@ -174,7 +174,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
         MPlaceTy<'tcx, M::PointerTag>,
         Vec<PathElem>,
     >>,
-    ecx: &'rt InterpretCx<'mir, 'tcx, M>,
+    ecx: &'rt InterpCx<'mir, 'tcx, M>,
 }
 
 impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> {
@@ -259,7 +259,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
     type V = OpTy<'tcx, M::PointerTag>;
 
     #[inline(always)]
-    fn ecx(&self) -> &InterpretCx<'mir, 'tcx, M> {
+    fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
         &self.ecx
     }
 
@@ -628,7 +628,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// This function checks the data at `op`. `op` is assumed to cover valid memory if it
     /// is an indirect operand.
     /// It will error if the bits at the destination do not match the ones described by the layout.
diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs
index d04dc3ab37e..783d2522637 100644
--- a/src/librustc_mir/interpret/visitor.rs
+++ b/src/librustc_mir/interpret/visitor.rs
@@ -8,7 +8,7 @@ use rustc::mir::interpret::{
 };
 
 use super::{
-    Machine, InterpretCx, MPlaceTy, OpTy,
+    Machine, InterpCx, MPlaceTy, OpTy,
 };
 
 // A thing that we can project into, and that has a layout.
@@ -21,7 +21,7 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Copy {
     /// Makes this into an `OpTy`.
     fn to_op(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>>;
 
     /// Creates this from an `MPlaceTy`.
@@ -30,14 +30,14 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Copy {
     /// Projects to the given enum variant.
     fn project_downcast(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         variant: VariantIdx,
     ) -> InterpResult<'tcx, Self>;
 
     /// Projects to the n-th field.
     fn project_field(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         field: u64,
     ) -> InterpResult<'tcx, Self>;
 }
@@ -53,7 +53,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tcx, M::
     #[inline(always)]
     fn to_op(
         self,
-        _ecx: &InterpretCx<'mir, 'tcx, M>,
+        _ecx: &InterpCx<'mir, 'tcx, M>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         Ok(self)
     }
@@ -66,7 +66,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tcx, M::
     #[inline(always)]
     fn project_downcast(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         variant: VariantIdx,
     ) -> InterpResult<'tcx, Self> {
         ecx.operand_downcast(self, variant)
@@ -75,7 +75,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tcx, M::
     #[inline(always)]
     fn project_field(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         field: u64,
     ) -> InterpResult<'tcx, Self> {
         ecx.operand_field(self, field)
@@ -91,7 +91,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for MPlaceTy<'tcx,
     #[inline(always)]
     fn to_op(
         self,
-        _ecx: &InterpretCx<'mir, 'tcx, M>,
+        _ecx: &InterpCx<'mir, 'tcx, M>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         Ok(self.into())
     }
@@ -104,7 +104,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for MPlaceTy<'tcx,
     #[inline(always)]
     fn project_downcast(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         variant: VariantIdx,
     ) -> InterpResult<'tcx, Self> {
         ecx.mplace_downcast(self, variant)
@@ -113,7 +113,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for MPlaceTy<'tcx,
     #[inline(always)]
     fn project_field(
         self,
-        ecx: &InterpretCx<'mir, 'tcx, M>,
+        ecx: &InterpCx<'mir, 'tcx, M>,
         field: u64,
     ) -> InterpResult<'tcx, Self> {
         ecx.mplace_field(self, field)
@@ -126,9 +126,9 @@ macro_rules! make_value_visitor {
         pub trait $visitor_trait_name<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
             type V: Value<'mir, 'tcx, M>;
 
-            /// The visitor must have an `InterpretCx` in it.
+            /// The visitor must have an `InterpCx` in it.
             fn ecx(&$($mutability)? self)
-                -> &$($mutability)? InterpretCx<'mir, 'tcx, M>;
+                -> &$($mutability)? InterpCx<'mir, 'tcx, M>;
 
             // Recursive actions, ready to be overloaded.
             /// Visits the given value, dispatching as appropriate to more specialized visitors.
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index cb02e1a778c..b85149cf556 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,6 +24,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(slice_concat_ext)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
+#![feature(mem_take)]
 
 #![recursion_limit="256"]
 
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index bb2738d5aa4..097d76925c8 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -281,10 +281,10 @@ impl<'tcx> InliningMap<'tcx> {
     }
 }
 
-pub fn collect_crate_mono_items<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn collect_crate_mono_items(
+    tcx: TyCtxt<'_>,
     mode: MonoItemCollectionMode,
-) -> (FxHashSet<MonoItem<'tcx>>, InliningMap<'tcx>) {
+) -> (FxHashSet<MonoItem<'_>>, InliningMap<'_>) {
     let roots = time(tcx.sess, "collecting roots", || {
         collect_roots(tcx, mode)
     });
@@ -315,7 +315,7 @@ pub fn collect_crate_mono_items<'tcx>(
 
 // Find all non-generic items by walking the HIR. These items serve as roots to
 // start monomorphizing from.
-fn collect_roots<'tcx>(tcx: TyCtxt<'tcx>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'tcx>> {
+fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("Collecting roots");
     let mut roots = Vec::new();
 
@@ -912,7 +912,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
     }
 }
 
-fn create_fn_mono_item<'tcx>(instance: Instance<'tcx>) -> MonoItem<'tcx> {
+fn create_fn_mono_item(instance: Instance<'_>) -> MonoItem<'_> {
     debug!("create_fn_mono_item(instance={})", instance);
     MonoItem::Fn(instance)
 }
@@ -1114,7 +1114,7 @@ impl RootCollector<'_, 'v> {
     }
 }
 
-fn item_requires_monomorphization<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     let generics = tcx.generics_of(def_id);
     generics.requires_monomorphization(tcx)
 }
@@ -1243,7 +1243,7 @@ fn collect_neighbours<'tcx>(
     }
 }
 
-fn def_id_to_string<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> String {
+fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String {
     let mut output = String::new();
     let printer = DefPathBasedNames::new(tcx, false, false);
     printer.push_def_path(def_id, &mut output);
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 32e4d4f437a..a934c921d92 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -839,10 +839,10 @@ where
     }
 }
 
-fn collect_and_partition_mono_items<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn collect_and_partition_mono_items(
+    tcx: TyCtxt<'_>,
     cnum: CrateNum,
-) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>) {
+) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'_>>>>) {
     assert_eq!(cnum, LOCAL_CRATE);
 
     let collection_mode = match tcx.sess.opts.debugging_opts.print_mono_items {
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 7987095a334..32b964dbadf 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -829,7 +829,7 @@ fn build_call_shim<'tcx>(
     body
 }
 
-pub fn build_adt_ctor<'tcx>(tcx: TyCtxt<'tcx>, ctor_id: DefId) -> &'tcx Body<'tcx> {
+pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> {
     debug_assert!(tcx.is_constructor(ctor_id));
 
     let span = tcx.hir().span_if_local(ctor_id)
diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs
index e01017d7c9b..de5af0a46b5 100644
--- a/src/librustc_mir/transform/add_retag.rs
+++ b/src/librustc_mir/transform/add_retag.rs
@@ -14,8 +14,8 @@ pub struct AddRetag;
 /// after the assignment, we can be sure to obtain the same place value.
 /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
 /// copies.  Data races are UB.)
-fn is_stable<'tcx>(
-    place: &Place<'tcx>,
+fn is_stable(
+    place: &Place<'_>,
 ) -> bool {
     use rustc::mir::Place::*;
 
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 24df3549be4..9898ba89773 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -480,11 +480,11 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
     }
 }
 
-fn check_unused_unsafe<'a, 'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn check_unused_unsafe(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
     used_unsafe: &FxHashSet<hir::HirId>,
-    unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>,
+    unsafe_blocks: &mut Vec<(hir::HirId, bool)>,
 ) {
     let body_id =
         tcx.hir().as_local_hir_id(def_id).and_then(|hir_id| {
@@ -506,7 +506,7 @@ fn check_unused_unsafe<'a, 'tcx>(
     hir::intravisit::Visitor::visit_body(&mut visitor, body);
 }
 
-fn unsafety_check_result<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> UnsafetyCheckResult {
+fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: DefId) -> UnsafetyCheckResult {
     debug!("unsafety_violations({:?})", def_id);
 
     // N.B., this borrow is valid because all the consumers of
@@ -545,7 +545,7 @@ fn unsafety_check_result<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> UnsafetyChec
     }
 }
 
-fn unsafe_derive_on_repr_packed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) {
     let lint_hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(||
         bug!("checking unsafety for non-local def id {:?}", def_id));
 
@@ -602,7 +602,7 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet<hir::HirId>, id
     db.emit();
 }
 
-fn builtin_derive_def_id<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<DefId> {
+fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     debug!("builtin_derive_def_id({:?})", def_id);
     if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
         if tcx.has_attr(impl_def_id, sym::automatically_derived) {
@@ -618,7 +618,7 @@ fn builtin_derive_def_id<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<DefId
     }
 }
 
-pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
     debug!("check_unsafety({:?})", def_id);
 
     // closures are handled by their parent fn.
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index c7a2fdd9383..29480f88fce 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -23,7 +23,7 @@ use rustc::ty::layout::{
 };
 
 use crate::interpret::{
-    self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy,
+    self, InterpCx, ScalarMaybeUndef, Immediate, OpTy,
     ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
 };
 use crate::const_eval::{
@@ -117,7 +117,7 @@ type Const<'tcx> = OpTy<'tcx>;
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
-    ecx: InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
+    ecx: InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
     tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
     can_const_prop: IndexVec<Local, bool>,
@@ -202,7 +202,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
         // If the local is `Unitialized` or `Dead` then we haven't propagated a value into it.
         //
-        // `InterpretCx::access_local()` mostly takes care of this for us however, for ZSTs,
+        // `InterpCx::access_local()` mostly takes care of this for us however, for ZSTs,
         // it will synthesize a value for us. In doing so, that will cause the
         // `get_const(l).is_empty()` assert right before we call `set_const()` in `visit_statement`
         // to fail.
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index 243820ba7d0..a6fb555f20b 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -14,7 +14,7 @@ use crate::util as mir_util;
 pub struct Marker(pub &'static str);
 
 impl MirPass for Marker {
-    fn name<'a>(&'a self) -> Cow<'a, str> {
+    fn name(&self) -> Cow<'_, str> {
         Cow::Borrowed(self.0)
     }
 
@@ -52,7 +52,7 @@ pub fn on_mir_pass<'tcx>(
     }
 }
 
-pub fn emit_mir<'tcx>(tcx: TyCtxt<'tcx>, outputs: &OutputFilenames) -> io::Result<()> {
+pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> {
     let path = outputs.path(OutputType::Mir);
     let mut f = File::create(&path)?;
     mir_util::write_mir_pretty(tcx, None, &mut f)?;
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 7b961e97a10..2ed3f7d5c26 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -68,7 +68,7 @@ use crate::transform::simplify;
 use crate::transform::no_landing_pads::no_landing_pads;
 use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation};
 use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location};
-use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
+use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals, RequiresStorage};
 use crate::util::dump_mir;
 use crate::util::liveness;
 
@@ -437,16 +437,18 @@ fn locals_live_across_suspend_points(
 
     // Calculate the MIR locals which have been previously
     // borrowed (even if they are still active).
-    // This is only used for immovable generators.
-    let borrowed_locals = if !movable {
-        let analysis = HaveBeenBorrowedLocals::new(body);
-        let result =
-            do_dataflow(tcx, body, def_id, &[], &dead_unwinds, analysis,
-                        |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
-        Some((analysis, result))
-    } else {
-        None
-    };
+    let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body);
+    let borrowed_locals_result =
+        do_dataflow(tcx, body, def_id, &[], &dead_unwinds, borrowed_locals_analysis,
+                    |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+
+    // Calculate the MIR locals that we actually need to keep storage around
+    // for.
+    let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
+    let requires_storage =
+        do_dataflow(tcx, body, def_id, &[], &dead_unwinds, requires_storage_analysis,
+                    |bd, p| DebugFormatted::new(&bd.body().local_decls[p]));
+    let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_result);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len());
@@ -471,10 +473,10 @@ fn locals_live_across_suspend_points(
                 statement_index: data.statements.len(),
             };
 
-            if let Some((ref analysis, ref result)) = borrowed_locals {
+            if !movable {
                 let borrowed_locals = state_for_location(loc,
-                                                         analysis,
-                                                         result,
+                                                         &borrowed_locals_analysis,
+                                                         &borrowed_locals_result,
                                                          body);
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
                 // This is correct for movable generators since borrows cannot live across
@@ -489,27 +491,34 @@ fn locals_live_across_suspend_points(
                 liveness.outs[block].union(&borrowed_locals);
             }
 
-            let mut storage_liveness = state_for_location(loc,
-                                                          &storage_live_analysis,
-                                                          &storage_live,
-                                                          body);
+            let storage_liveness = state_for_location(loc,
+                                                      &storage_live_analysis,
+                                                      &storage_live,
+                                                      body);
 
             // Store the storage liveness for later use so we can restore the state
             // after a suspension point
             storage_liveness_map.insert(block, storage_liveness.clone());
 
-            // Mark locals without storage statements as always having live storage
-            storage_liveness.union(&ignored.0);
+            let mut storage_required = state_for_location(loc,
+                                                          &requires_storage_analysis,
+                                                          &requires_storage,
+                                                          body);
+
+            // Mark locals without storage statements as always requiring storage
+            storage_required.union(&ignored.0);
 
             // Locals live are live at this point only if they are used across
             // suspension points (the `liveness` variable)
-            // and their storage is live (the `storage_liveness` variable)
-            let mut live_locals_here = storage_liveness;
+            // and their storage is required (the `storage_required` variable)
+            let mut live_locals_here = storage_required;
             live_locals_here.intersect(&liveness.outs[block]);
 
             // The generator argument is ignored
             live_locals_here.remove(self_arg());
 
+            debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here);
+
             // Add the locals live at this suspension point to the set of locals which live across
             // any suspension points
             live_locals.union(&live_locals_here);
@@ -517,6 +526,7 @@ fn locals_live_across_suspend_points(
             live_locals_at_suspension_points.push(live_locals_here);
         }
     }
+    debug!("live_locals = {:?}", live_locals);
 
     // Renumber our liveness_map bitsets to include only the locals we are
     // saving.
@@ -529,8 +539,8 @@ fn locals_live_across_suspend_points(
         body,
         &live_locals,
         &ignored,
-        storage_live,
-        storage_live_analysis);
+        requires_storage,
+        requires_storage_analysis);
 
     LivenessInfo {
         live_locals,
@@ -567,8 +577,8 @@ fn compute_storage_conflicts(
     body: &'mir Body<'tcx>,
     stored_locals: &liveness::LiveVarSet,
     ignored: &StorageIgnored,
-    storage_live: DataflowResults<'tcx, MaybeStorageLive<'mir, 'tcx>>,
-    _storage_live_analysis: MaybeStorageLive<'mir, 'tcx>,
+    requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>,
+    _requires_storage_analysis: RequiresStorage<'mir, 'tcx>,
 ) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
     assert_eq!(body.local_decls.len(), ignored.0.domain_size());
     assert_eq!(body.local_decls.len(), stored_locals.domain_size());
@@ -584,9 +594,9 @@ fn compute_storage_conflicts(
     let mut visitor = StorageConflictVisitor {
         body,
         stored_locals: &stored_locals,
-        local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len())
+        local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()),
     };
-    let mut state = FlowAtLocation::new(storage_live);
+    let mut state = FlowAtLocation::new(requires_storage);
     visitor.analyze_results(&mut state);
     let local_conflicts = visitor.local_conflicts;
 
@@ -627,7 +637,7 @@ struct StorageConflictVisitor<'body, 'tcx, 's> {
 impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx>
     for StorageConflictVisitor<'body, 'tcx, 's>
 {
-    type FlowState = FlowAtLocation<'tcx, MaybeStorageLive<'body, 'tcx>>;
+    type FlowState = FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>;
 
     fn body(&self) -> &'body Body<'tcx> {
         self.body
@@ -657,7 +667,7 @@ impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx>
 
 impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> {
     fn apply_state(&mut self,
-                   flow_state: &FlowAtLocation<'tcx, MaybeStorageLive<'body, 'tcx>>,
+                   flow_state: &FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>,
                    loc: Location) {
         // Ignore unreachable blocks.
         match self.body.basic_blocks()[loc.block].terminator().kind {
@@ -1018,14 +1028,14 @@ fn create_generator_resume_function<'tcx>(
     dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(()) );
 }
 
-fn source_info<'tcx>(body: &Body<'tcx>) -> SourceInfo {
+fn source_info(body: &Body<'_>) -> SourceInfo {
     SourceInfo {
         span: body.span,
         scope: OUTERMOST_SOURCE_SCOPE,
     }
 }
 
-fn insert_clean_drop<'tcx>(body: &mut Body<'tcx>) -> BasicBlock {
+fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
     let return_block = insert_term_block(body, TerminatorKind::Return);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 81d91dcd0a9..7f43c4a3e89 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -50,13 +50,13 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn is_mir_available<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     tcx.mir_keys(def_id.krate).contains(&def_id)
 }
 
 /// Finds the full set of `DefId`s within the current crate that have
 /// MIR associated with them.
-fn mir_keys<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx DefIdSet {
+fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
     assert_eq!(krate, LOCAL_CRATE);
 
     let mut set = DefIdSet::default();
@@ -94,7 +94,7 @@ fn mir_keys<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx DefIdSet {
     tcx.arena.alloc(set)
 }
 
-fn mir_built<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
+fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
     let mir = build::mir_build(tcx, def_id);
     tcx.alloc_steal_mir(mir)
 }
@@ -137,7 +137,7 @@ pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
 /// pass will be named after the type, and it will consist of a main
 /// loop that goes over each available MIR and applies `run_pass`.
 pub trait MirPass {
-    fn name<'a>(&'a self) -> Cow<'a, str> {
+    fn name(&self) -> Cow<'_, str> {
         default_name::<Self>()
     }
 
@@ -192,7 +192,7 @@ pub fn run_passes(
     }
 }
 
-fn mir_const<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
+fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<Body<'_>> {
     // Unsafety check uses the raw mir, so make sure it is run
     let _ = tcx.unsafety_check_result(def_id);
 
@@ -223,7 +223,7 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal<Body<'tcx>> {
     tcx.alloc_steal_mir(body)
 }
 
-fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> {
+fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> {
     if tcx.is_constructor(def_id) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index f082b5e5a04..3e52d3ee9bb 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1473,7 +1473,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn mir_const_qualif<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> (u8, &'tcx BitSet<Local>) {
+fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet<Local>) {
     // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
     // cannot yet be stolen), because `mir_validated()`, which steals
     // from `mir_const(), forces this query to execute before
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index f226f15c009..2eed9d453f2 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -53,7 +53,7 @@ pub fn simplify_cfg(body: &mut Body<'_>) {
 }
 
 impl MirPass for SimplifyCfg {
-    fn name<'a>(&'a self) -> Cow<'a, str> {
+    fn name(&self) -> Cow<'_, str> {
         Cow::Borrowed(&self.label)
     }
 
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 0c63a8d9c96..f39c71ef42d 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -15,7 +15,7 @@ impl SimplifyBranches {
 }
 
 impl MirPass for SimplifyBranches {
-    fn name<'a>(&'a self) -> Cow<'a, str> {
+    fn name(&self) -> Cow<'_, str> {
         Cow::Borrowed(&self.label)
     }
 
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
index fac752dbf02..59821440c66 100644
--- a/src/librustc_mir/util/def_use.rs
+++ b/src/librustc_mir/util/def_use.rs
@@ -31,7 +31,7 @@ impl DefUseAnalysis {
         self.clear();
 
         let mut finder = DefUseFinder {
-            info: mem::replace(&mut self.info, IndexVec::new()),
+            info: mem::take(&mut self.info),
         };
         finder.visit_body(body);
         self.info = finder.info
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index 1d876d7bddb..9d142d9b700 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -8,8 +8,8 @@ use std::io::{self, Write};
 use super::pretty::dump_mir_def_ids;
 
 /// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'tcx, W>(
-    tcx: TyCtxt<'tcx>,
+pub fn write_mir_graphviz<W>(
+    tcx: TyCtxt<'_>,
     single: Option<DefId>,
     w: &mut W,
 ) -> io::Result<()>
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index cf0fc09472b..b42eebc7ee3 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -56,8 +56,8 @@ pub struct LivenessResult {
 
 /// Computes which local variables are live within the given function
 /// `mir`, including drops.
-pub fn liveness_of_locals<'tcx>(
-    body: &Body<'tcx>,
+pub fn liveness_of_locals(
+    body: &Body<'_>,
 ) -> LivenessResult {
     let num_live_vars = body.local_decls.len();
 
@@ -75,9 +75,24 @@ pub fn liveness_of_locals<'tcx>(
 
     let mut bits = LiveVarSet::new_empty(num_live_vars);
 
-    // queue of things that need to be re-processed, and a set containing
-    // the things currently in the queue
-    let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_all(body.basic_blocks().len());
+    // The dirty queue contains the set of basic blocks whose entry sets have changed since they
+    // were last processed. At the start of the analysis, we initialize the queue in post-order to
+    // make it more likely that the entry set for a given basic block will have the effects of all
+    // its successors in the CFG applied before it is processed.
+    //
+    // FIXME(ecstaticmorse): Reverse post-order on the reverse CFG may generate a better iteration
+    // order when cycles are present, but the overhead of computing the reverse CFG may outweigh
+    // any benefits. Benchmark this and find out.
+    let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks().len());
+    for (bb, _) in traversal::postorder(body) {
+        dirty_queue.insert(bb);
+    }
+
+    // Add blocks which are not reachable from START_BLOCK to the work queue. These blocks will
+    // be processed after the ones added above.
+    for bb in body.basic_blocks().indices() {
+        dirty_queue.insert(bb);
+    }
 
     let predecessors = body.predecessors();
 
@@ -228,8 +243,8 @@ impl<'tcx> Visitor<'tcx> for DefsUsesVisitor
     }
 }
 
-fn block<'tcx>(
-    b: &BasicBlockData<'tcx>,
+fn block(
+    b: &BasicBlockData<'_>,
     locals: usize,
 ) -> DefsUses {
     let mut visitor = DefsUsesVisitor {
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs
index 719029dbaac..fd2a5e452ce 100644
--- a/src/librustc_mir/util/mod.rs
+++ b/src/librustc_mir/util/mod.rs
@@ -21,7 +21,7 @@ pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
 pub use self::graphviz::write_node_label as write_graphviz_node_label;
 
 /// If possible, suggest replacing `ref` with `ref mut`.
-pub fn suggest_ref_mut<'tcx>(tcx: TyCtxt<'tcx>, binding_span: Span) -> Option<(String)> {
+pub fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> {
     let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap();
     if hi_src.starts_with("ref")
         && hi_src["ref".len()..].starts_with(Pattern_White_Space)
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 2da9c5adf9b..56063596299 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -837,13 +837,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                                  the relevant `fold_*()` method in `PlaceholderExpander`?");
     }
 
-    fn visit_fn_header(&mut self, header: &'a FnHeader) {
-        if header.asyncness.node.is_async() && self.session.rust_2015() {
-            struct_span_err!(self.session, header.asyncness.span, E0670,
-                             "`async fn` is not permitted in the 2015 edition").emit();
-        }
-    }
-
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         match ii.node {
             ImplItemKind::Method(ref sig, _) => {
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 6936aedb9de..e7f6abc410a 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -38,7 +38,7 @@ pub fn print_hir_stats(krate: &hir::Crate) {
     collector.print("HIR STATS");
 }
 
-pub fn print_ast_stats<'v>(krate: &'v ast::Crate, title: &str) {
+pub fn print_ast_stats(krate: &ast::Crate, title: &str) {
     let mut collector = StatCollector {
         krate: None,
         data: FxHashMap::default(),
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index 8f790d13285..6b1ce578240 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -14,7 +14,7 @@ use rustc::ty::TyCtxt;
 use syntax::ast::Attribute;
 use syntax::symbol::sym;
 
-pub fn test_layout<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_layout(tcx: TyCtxt<'_>) {
     if tcx.features().rustc_attrs {
         // if the `rustc_attrs` feature is not enabled, don't bother testing layout
         tcx.hir()
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index ed0a78b4652..616e6974110 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -45,7 +45,7 @@ struct CheckLoopVisitor<'a, 'hir> {
     cx: Context,
 }
 
-fn check_mod_loops<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
         sess: &tcx.sess,
         hir_map: &tcx.hir(),
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index bc1151974bb..e14fa07fbbf 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -39,7 +39,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn const_is_rvalue_promotable_to_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn const_is_rvalue_promotable_to_static(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     assert!(def_id.is_local());
 
     let hir_id = tcx.hir().as_local_hir_id(def_id)
@@ -48,7 +48,7 @@ fn const_is_rvalue_promotable_to_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId)
     tcx.rvalue_promotable_map(def_id).contains(&body_id.hir_id.local_id)
 }
 
-fn rvalue_promotable_map<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ItemLocalSet {
+fn rvalue_promotable_map(tcx: TyCtxt<'_>, def_id: DefId) -> &ItemLocalSet {
     let outer_def_id = tcx.closure_base_def_id(def_id);
     if outer_def_id != def_id {
         return tcx.rvalue_promotable_map(outer_def_id);
diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs
index d3ac597160f..816e283a104 100644
--- a/src/librustc_plugin/build.rs
+++ b/src/librustc_plugin/build.rs
@@ -30,11 +30,11 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
 }
 
 /// Finds the function marked with `#[plugin_registrar]`, if any.
-pub fn find_plugin_registrar<'tcx>(tcx: TyCtxt<'tcx>) -> Option<DefId> {
+pub fn find_plugin_registrar(tcx: TyCtxt<'_>) -> Option<DefId> {
     tcx.plugin_registrar_fn(LOCAL_CRATE)
 }
 
-fn plugin_registrar_fn<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> Option<DefId> {
+fn plugin_registrar_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<DefId> {
     assert_eq!(cnum, LOCAL_CRATE);
 
     let mut finder = RegistrarFinder { registrars: Vec::new() };
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index 16d484e2a98..ec2855f826a 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -6,7 +6,7 @@ use rustc::util::nodemap::FxHashMap;
 
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
 use syntax::ext::base::MacroExpanderFn;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::Symbol;
 use syntax::ast;
 use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
@@ -77,7 +77,7 @@ impl<'a> Registry<'a> {
     ///
     /// Returns empty slice in case the plugin was loaded
     /// with `--extra-plugins`
-    pub fn args<'b>(&'b self) -> &'b [ast::NestedMetaItem] {
+    pub fn args(&self) -> &[ast::NestedMetaItem] {
         self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
     }
 
@@ -85,9 +85,6 @@ impl<'a> Registry<'a> {
     ///
     /// This is the most general hook into `libsyntax`'s expansion behavior.
     pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: SyntaxExtension) {
-        if name == sym::macro_rules {
-            panic!("user-defined macros may not be named `macro_rules`");
-        }
         if extension.def_info.is_none() {
             extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
         }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 3e98200e532..339021f511a 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -337,7 +337,7 @@ fn item_tables<'a, 'tcx>(
     if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables }
 }
 
-fn min<'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'tcx>) -> ty::Visibility {
+fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
     if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
 }
 
@@ -384,14 +384,14 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
 trait VisibilityLike: Sized {
     const MAX: Self;
     const SHALLOW: bool = false;
-    fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self;
+    fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self;
 
     // Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
     // associated types for which we can't determine visibility precisely.
-    fn of_impl<'a, 'tcx>(
+    fn of_impl(
         hir_id: hir::HirId,
-        tcx: TyCtxt<'tcx>,
-        access_levels: &'a AccessLevels,
+        tcx: TyCtxt<'_>,
+        access_levels: &AccessLevels,
     ) -> Self {
         let mut find = FindMin { tcx, access_levels, min: Self::MAX };
         let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
@@ -404,7 +404,7 @@ trait VisibilityLike: Sized {
 }
 impl VisibilityLike for ty::Visibility {
     const MAX: Self = ty::Visibility::Public;
-    fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self {
+    fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
         min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx)
     }
 }
@@ -420,7 +420,7 @@ impl VisibilityLike for Option<AccessLevel> {
     // both "shallow" version of its self type and "shallow" version of its trait if it exists
     // (which require reaching the `DefId`s in them).
     const SHALLOW: bool = true;
-    fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self {
+    fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
         cmp::min(if let Some(hir_id) = find.tcx.hir().as_local_hir_id(def_id) {
             find.access_levels.map.get(&hir_id).cloned()
         } else {
@@ -1828,7 +1828,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn check_mod_privacy<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: DefId) {
     let empty_tables = ty::TypeckTables::empty(None);
 
     // Check privacy of names not checked in previous compilation stages.
@@ -1855,7 +1855,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
     intravisit::walk_mod(&mut visitor, module, hir_id);
 }
 
-fn privacy_access_levels<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx AccessLevels {
+fn privacy_access_levels(tcx: TyCtxt<'_>, krate: CrateNum) -> &AccessLevels {
     assert_eq!(krate, LOCAL_CRATE);
 
     // Build up a set of all exported items in the AST. This is a set of all
@@ -1879,7 +1879,7 @@ fn privacy_access_levels<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) -> &'tcx Acce
     tcx.arena.alloc(visitor.access_levels)
 }
 
-fn check_private_in_public<'tcx>(tcx: TyCtxt<'tcx>, krate: CrateNum) {
+fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) {
     assert_eq!(krate, LOCAL_CRATE);
 
     let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 81adfac0a29..05247600a4d 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4,9 +4,10 @@
 
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
+#![feature(mem_take)]
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(type_alias_enum_variants)]
+#![cfg_attr(bootstrap, feature(type_alias_enum_variants))]
 
 #![recursion_limit="256"]
 
@@ -198,9 +199,9 @@ enum ResolutionError<'a> {
 ///
 /// This takes the error provided, combines it with the span and any additional spans inside the
 /// error and emits it.
-fn resolve_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
-                            span: Span,
-                            resolution_error: ResolutionError<'a>) {
+fn resolve_error(resolver: &Resolver<'_>,
+                 span: Span,
+                 resolution_error: ResolutionError<'_>) {
     resolve_struct_error(resolver, span, resolution_error).emit();
 }
 
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 392a46a262f..d8d08107b82 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -946,7 +946,7 @@ impl<'a> Resolver<'a> {
         };
 
         let macro_resolutions =
-            mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new());
+            mem::take(&mut *module.multi_segment_macro_resolutions.borrow_mut());
         for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions {
             // FIXME: Path resolution will ICE if segment IDs present.
             for seg in &mut path { seg.id = None; }
@@ -973,7 +973,7 @@ impl<'a> Resolver<'a> {
         }
 
         let macro_resolutions =
-            mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
+            mem::take(&mut *module.single_segment_macro_resolutions.borrow_mut());
         for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
             match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
                                                             &parent_scope, true, true, ident.span) {
@@ -998,7 +998,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
+        let builtin_attrs = mem::take(&mut *module.builtin_attrs.borrow_mut());
         for (ident, parent_scope) in builtin_attrs {
             let _ = self.early_resolve_ident_in_lexical_scope(
                 ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
@@ -1109,9 +1109,6 @@ impl<'a> Resolver<'a> {
                         current_legacy_scope: &mut LegacyScope<'a>) {
         self.local_macro_def_scopes.insert(item.id, self.current_module);
         let ident = item.ident;
-        if ident.name == sym::macro_rules {
-            self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
-        }
 
         let def_id = self.definitions.local_def_id(item.id);
         let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index f69849bb4a9..404d728d880 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -682,7 +682,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
         while self.indeterminate_imports.len() < prev_num_indeterminates {
             prev_num_indeterminates = self.indeterminate_imports.len();
-            for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) {
+            for import in mem::take(&mut self.indeterminate_imports) {
                 match self.resolve_import(&import) {
                     true => self.determined_imports.push(import),
                     false => self.indeterminate_imports.push(import),
diff --git a/src/librustc_target/spec/windows_msvc_base.rs b/src/librustc_target/spec/windows_msvc_base.rs
index fdd747cdb86..b139083e99f 100644
--- a/src/librustc_target/spec/windows_msvc_base.rs
+++ b/src/librustc_target/spec/windows_msvc_base.rs
@@ -19,6 +19,10 @@ pub fn opts() -> TargetOptions {
         target_family: Some("windows".to_string()),
         is_like_windows: true,
         is_like_msvc: true,
+        // set VSLANG to 1033 can prevent link.exe from using
+        // language packs, and avoid generating Non-UTF-8 error
+        // messages if a link error occurred.
+        link_env: vec![("VSLANG".to_string(), "1033".to_string())],
         pre_link_args: args,
         crt_static_allows_dylibs: true,
         crt_static_respected: true,
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index bbb0825ee08..5c23ad4a4ed 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -17,6 +17,7 @@ use rustc::infer::canonical::{
     CanonicalVarValues,
     OriginalQueryValues,
     QueryResponse,
+    QueryRegionConstraints,
     Certainty,
 };
 use rustc::traits::{
@@ -151,14 +152,14 @@ impl context::AggregateOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> {
         let solution = constrained_subst.unchecked_map(|cs| match ambiguous {
             true => QueryResponse {
                 var_values: cs.subst.make_identity(self.tcx),
-                region_constraints: Vec::new(),
+                region_constraints: QueryRegionConstraints::default(),
                 certainty: Certainty::Ambiguous,
                 value: (),
             },
 
             false => QueryResponse {
                 var_values: cs.subst,
-                region_constraints: Vec::new(),
+                region_constraints: QueryRegionConstraints::default(),
 
                 // FIXME: restore this later once we get better at handling regions
                 // region_constraints: cs.constraints
diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
index 8e4b9da6de2..6e8eed0f907 100644
--- a/src/librustc_traits/chalk_context/program_clauses/primitive.rs
+++ b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
@@ -15,7 +15,7 @@ use crate::lowering::Lower;
 use crate::generic_types;
 use std::iter;
 
-crate fn wf_clause_for_raw_ptr<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Clauses<'tcx> {
+crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
     let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
 
     let wf_clause = ProgramClause {
@@ -29,13 +29,13 @@ crate fn wf_clause_for_raw_ptr<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability)
     tcx.mk_clauses(iter::once(wf_clause))
 }
 
-crate fn wf_clause_for_fn_ptr<'tcx>(
-    tcx: TyCtxt<'tcx>,
+crate fn wf_clause_for_fn_ptr(
+    tcx: TyCtxt<'_>,
     arity_and_output: usize,
     variadic: bool,
     unsafety: hir::Unsafety,
     abi: abi::Abi,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
     let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
 
     let wf_clause = ProgramClause {
@@ -50,7 +50,7 @@ crate fn wf_clause_for_fn_ptr<'tcx>(
     tcx.mk_clauses(iter::once(wf_clause))
 }
 
-crate fn wf_clause_for_slice<'tcx>(tcx: TyCtxt<'tcx>) -> Clauses<'tcx> {
+crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> {
     let ty = generic_types::bound(tcx, 0);
     let slice_ty = tcx.mk_slice(ty);
 
@@ -111,7 +111,7 @@ crate fn wf_clause_for_array<'tcx>(
     tcx.mk_clauses(iter::once(wf_clause))
 }
 
-crate fn wf_clause_for_tuple<'tcx>(tcx: TyCtxt<'tcx>, arity: usize) -> Clauses<'tcx> {
+crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> {
     let type_list = generic_types::type_list(tcx, arity);
     let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
 
@@ -152,7 +152,7 @@ crate fn wf_clause_for_tuple<'tcx>(tcx: TyCtxt<'tcx>, arity: usize) -> Clauses<'
     tcx.mk_clauses(iter::once(wf_clause))
 }
 
-crate fn wf_clause_for_ref<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Clauses<'tcx> {
+crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> {
     let region = tcx.mk_region(
         ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
     );
@@ -176,7 +176,7 @@ crate fn wf_clause_for_ref<'tcx>(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> C
     tcx.mk_clauses(iter::once(wf_clause))
 }
 
-crate fn wf_clause_for_fn_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     let fn_def = generic_types::fn_def(tcx, def_id);
 
     let wf_clause = ProgramClause {
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 3abd7e90cf1..ecd888b6069 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -279,10 +279,10 @@ fn dtorck_constraint_for_ty<'tcx>(
 }
 
 /// Calculates the dtorck constraint for a type.
-crate fn adt_dtorck_constraint<'tcx>(
-    tcx: TyCtxt<'tcx>,
+crate fn adt_dtorck_constraint(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> Result<DtorckConstraint<'tcx>, NoSolution> {
+) -> Result<DtorckConstraint<'_>, NoSolution> {
     let def = tcx.adt_def(def_id);
     let span = tcx.def_span(def_id);
     debug!("dtorck_constraint: {:?}", def);
@@ -313,7 +313,7 @@ crate fn adt_dtorck_constraint<'tcx>(
     Ok(result)
 }
 
-fn dedup_dtorck_constraint<'tcx>(c: &mut DtorckConstraint<'tcx>) {
+fn dedup_dtorck_constraint(c: &mut DtorckConstraint<'_>) {
     let mut outlives = FxHashSet::default();
     let mut dtorck_types = FxHashSet::default();
 
diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs
index 01736855831..9ff685bb4ee 100644
--- a/src/librustc_traits/lowering/environment.rs
+++ b/src/librustc_traits/lowering/environment.rs
@@ -160,7 +160,7 @@ crate fn program_clauses_for_env<'tcx>(
     );
 }
 
-crate fn environment<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Environment<'tcx> {
+crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> {
     use super::{Lower, IntoFromEnvGoal};
     use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
 
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 2a661310161..b0d9134c834 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -155,7 +155,7 @@ impl<'tcx> IntoWellFormedGoal for DomainGoal<'tcx> {
     }
 }
 
-crate fn program_clauses_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+crate fn program_clauses_for(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     // FIXME(eddyb) this should only be using `def_kind`.
     match tcx.def_key(def_id).disambiguated_data.data {
         DefPathData::TypeNs(..) => match tcx.def_kind(def_id) {
@@ -181,7 +181,7 @@ crate fn program_clauses_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<
     }
 }
 
-fn program_clauses_for_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
 
     // Rule Implemented-From-Env (see rustc guide)
@@ -337,7 +337,7 @@ fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
     tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::bind(clause))))
 }
 
-pub fn program_clauses_for_type_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> {
+pub fn program_clauses_for_type_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> {
     // Rule WellFormed-Type
     //
     // `struct Ty<P1..Pn> where WC1, ..., WCm`
@@ -411,10 +411,10 @@ pub fn program_clauses_for_type_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> C
     tcx.mk_clauses(iter::once(well_formed_clause).chain(from_env_clauses))
 }
 
-pub fn program_clauses_for_associated_type_def<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn program_clauses_for_associated_type_def(
+    tcx: TyCtxt<'_>,
     item_id: DefId,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
     // Rule ProjectionEq-Placeholder
     //
     // ```
@@ -549,10 +549,10 @@ pub fn program_clauses_for_associated_type_def<'tcx>(
     tcx.mk_clauses(clauses)
 }
 
-pub fn program_clauses_for_associated_type_value<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn program_clauses_for_associated_type_value(
+    tcx: TyCtxt<'_>,
     item_id: DefId,
-) -> Clauses<'tcx> {
+) -> Clauses<'_> {
     // Rule Normalize-From-Impl (see rustc guide)
     //
     // ```
@@ -611,7 +611,7 @@ pub fn program_clauses_for_associated_type_value<'tcx>(
     tcx.mk_clauses(iter::once(normalize_clause))
 }
 
-pub fn dump_program_clauses<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn dump_program_clauses(tcx: TyCtxt<'_>) {
     if !tcx.features().rustc_attrs {
         return;
     }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 0375ad4a08f..1792716d1fb 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -7,6 +7,7 @@ use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
 use crate::hir::def::{CtorOf, Res, DefKind};
 use crate::hir::def_id::DefId;
 use crate::hir::HirVec;
+use crate::hir::ptr::P;
 use crate::lint;
 use crate::middle::lang_items::SizedTraitLangItem;
 use crate::middle::resolve_lifetime as rl;
@@ -23,7 +24,6 @@ use crate::require_c_abi_if_c_variadic;
 use smallvec::SmallVec;
 use syntax::ast;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::symbol::sym;
 use syntax_pos::{DUMMY_SP, Span, MultiSpan};
@@ -34,7 +34,6 @@ use std::collections::BTreeSet;
 use std::iter;
 use std::slice;
 
-use super::{check_type_alias_enum_variants_enabled};
 use rustc_data_structures::fx::FxHashSet;
 
 #[derive(Debug)]
@@ -1595,7 +1594,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 });
                 if let Some(variant_def) = variant_def {
                     if permit_variants {
-                        check_type_alias_enum_variants_enabled(tcx, span);
                         tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
                         return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
                     } else {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index b435c99ad01..eeed5be8678 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -5,6 +5,7 @@ use errors::{Applicability, DiagnosticBuilder};
 use rustc::hir::{self, PatKind, Pat, ExprKind};
 use rustc::hir::def::{Res, DefKind, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
+use rustc::hir::ptr::P;
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::{ObligationCause, ObligationCauseCode};
@@ -12,7 +13,6 @@ use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::subst::Kind;
 use syntax::ast;
 use syntax::source_map::Spanned;
-use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
 use syntax_pos::hygiene::CompilerDesugaringKind;
@@ -458,7 +458,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 match ty.sty {
                                     ty::Array(..) | ty::Slice(..) => {
                                         err.help("the semantics of slice patterns changed \
-                                                  recently; see issue #23121");
+                                                  recently; see issue #62254");
                                     }
                                     _ => {}
                                 }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 4bd2f216224..94c76deade2 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -54,6 +54,7 @@ use crate::check::{FnCtxt, Needs};
 use errors::DiagnosticBuilder;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::hir::ptr::P;
 use rustc::infer::{Coercion, InferResult, InferOk};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
@@ -67,7 +68,6 @@ use rustc::ty::relate::RelateResult;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
 use syntax::feature_gate;
-use syntax::ptr::P;
 use syntax::symbol::sym;
 use syntax_pos;
 
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index a2621abf44d..c4c4e10a14c 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -29,7 +29,7 @@ use syntax_pos::Span;
 ///    struct/enum definition for the nominal type itself (i.e.
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
-pub fn check_drop_impl<'tcx>(tcx: TyCtxt<'tcx>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
+pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> {
     let dtor_self_type = tcx.type_of(drop_impl_did);
     let dtor_predicates = tcx.predicates_of(drop_impl_did);
     match dtor_self_type.sty {
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 21fa219a1ca..ccc20bd9585 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -20,13 +20,13 @@ use crate::astconv::AstConv as _;
 
 use errors::{Applicability, DiagnosticBuilder};
 use syntax::ast;
-use syntax::ptr::P;
 use syntax::symbol::{Symbol, LocalInternedString, kw, sym};
 use syntax::source_map::Span;
 use syntax::util::lev_distance::find_best_match_for_name;
 use rustc::hir;
 use rustc::hir::{ExprKind, QPath};
 use rustc::hir::def::{CtorKind, Res, DefKind};
+use rustc::hir::ptr::P;
 use rustc::infer;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::mir::interpret::GlobalId;
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 8c2b8d1565f..9b1a8913822 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -79,7 +79,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
 
 /// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
 /// and in libcore/intrinsics.rs
-pub fn check_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
+pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
     let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n)));
     let name = it.ident.as_str();
 
@@ -385,7 +385,7 @@ pub fn check_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
-pub fn check_platform_intrinsic_type<'tcx>(tcx: TyCtxt<'tcx>, it: &hir::ForeignItem) {
+pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) {
     let param = |n| {
         let name = InternedString::intern(&format!("P{}", n));
         tcx.mk_ty_param(n, name)
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index b492197870b..b8b65279fe7 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -26,7 +26,6 @@ use rustc::infer::{self, InferOk};
 use syntax::ast;
 use syntax_pos::Span;
 
-use crate::{check_type_alias_enum_variants_enabled};
 use self::probe::{IsSuggestion, ProbeScope};
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
@@ -417,8 +416,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
                 });
                 if let Some(variant_def) = variant_def {
-                    check_type_alias_enum_variants_enabled(tcx, span);
-
                     // Braced variants generate unusable names in value namespace (reserved for
                     // possible future use), so variants resolved as associated items may refer to
                     // them as well. It's ok to use the variant's id as a ctor id since an
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 661883f2ac1..bd4cf9d2086 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -970,9 +970,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
         debug!("pick: actual search failed, assemble diagnotics");
 
-        let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
+        let static_candidates = mem::take(&mut self.static_candidates);
         let private_candidate = self.private_candidate.take();
-        let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]);
+        let unsatisfied_predicates = mem::take(&mut self.unsatisfied_predicates);
 
         // things failed, so lets look at all traits, for diagnostic purposes now:
         self.reset();
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index fa1b07d2dcf..be00a6efe55 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -775,12 +775,12 @@ impl Ord for TraitInfo {
 }
 
 /// Retrieves all traits in this crate and any dependent crates.
-pub fn all_traits<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<TraitInfo> {
+pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
     tcx.all_traits(LOCAL_CRATE).iter().map(|&def_id| TraitInfo { def_id }).collect()
 }
 
 /// Computes all traits in this crate and any dependent crates.
-fn compute_all_traits<'tcx>(tcx: TyCtxt<'tcx>) -> Vec<DefId> {
+fn compute_all_traits(tcx: TyCtxt<'_>) -> Vec<DefId> {
     use hir::itemlikevisit;
 
     let mut traits = vec![];
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 37866bab900..fb7d681a72d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -93,6 +93,7 @@ use rustc::hir::def::{CtorOf, Res, DefKind};
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::ptr::P;
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
 use rustc::infer::{self, InferCtxt, InferOk, InferResult};
@@ -122,7 +123,6 @@ use syntax_pos::hygiene::CompilerDesugaringKind;
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::ptr::P;
 use syntax::source_map::{DUMMY_SP, original_sp};
 use syntax::symbol::{kw, sym};
 
@@ -698,31 +698,31 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> {
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
 }
 
-pub fn check_wf_new<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_wf_new(tcx: TyCtxt<'_>) {
     let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
     tcx.hir().krate().par_visit_all_item_likes(&mut visit);
 }
 
-fn check_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
 }
 
-fn typeck_item_bodies<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) {
+fn typeck_item_bodies(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     debug_assert!(crate_num == LOCAL_CRATE);
     tcx.par_body_owners(|body_owner_def_id| {
         tcx.ensure().typeck_tables_of(body_owner_def_id);
     });
 }
 
-fn check_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
     wfcheck::check_item_well_formed(tcx, def_id);
 }
 
-fn check_trait_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
     wfcheck::check_trait_item(tcx, def_id);
 }
 
-fn check_impl_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
     wfcheck::check_impl_item(tcx, def_id);
 }
 
@@ -742,7 +742,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn adt_destructor<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::Destructor> {
+fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
     tcx.calculate_dtor(def_id, &mut dropck::check_drop_impl)
 }
 
@@ -755,10 +755,10 @@ fn adt_destructor<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::Destruct
 /// may not succeed. In some cases where this function returns `None`
 /// (notably closures), `typeck_tables(def_id)` would wind up
 /// redirecting to the owning function.
-fn primary_body_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn primary_body_of(
+    tcx: TyCtxt<'_>,
     id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&'tcx hir::FnDecl>)> {
+) -> Option<(hir::BodyId, Option<&hir::FnDecl>)> {
     match tcx.hir().get(id) {
         Node::Item(item) => {
             match item.node {
@@ -796,7 +796,7 @@ fn primary_body_of<'tcx>(
     }
 }
 
-fn has_typeck_tables<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     // Closures' tables come from their outermost function,
     // as they are part of the same "inference environment".
     let outer_def_id = tcx.closure_base_def_id(def_id);
@@ -808,11 +808,11 @@ fn has_typeck_tables<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
     primary_body_of(tcx, id).is_some()
 }
 
-fn used_trait_imports<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx DefIdSet {
+fn used_trait_imports(tcx: TyCtxt<'_>, def_id: DefId) -> &DefIdSet {
     &*tcx.typeck_tables_of(def_id).used_trait_imports
 }
 
-fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TypeckTables<'tcx> {
+fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
     // Closures' tables come from their outermost function,
     // as they are part of the same "inference environment".
     let outer_def_id = tcx.closure_base_def_id(def_id);
@@ -856,7 +856,8 @@ fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TypeckT
             let revealed_ty = if tcx.features().impl_trait_in_bindings {
                 fcx.instantiate_opaque_types_from_value(
                     id,
-                    &expected_type
+                    &expected_type,
+                    body.value.span,
                 )
             } else {
                 expected_type
@@ -912,7 +913,7 @@ fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TypeckT
     tables
 }
 
-fn check_abi<'tcx>(tcx: TyCtxt<'tcx>, span: Span, abi: Abi) {
+fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
     if !tcx.sess.target.target.is_abi_supported(abi) {
         struct_span_err!(tcx.sess, span, E0570,
             "The ABI `{}` is not supported for the current target", abi).emit()
@@ -962,7 +963,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                 let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
                     self.fcx.instantiate_opaque_types_from_value(
                         self.parent_id,
-                        &o_ty
+                        &o_ty,
+                        ty.span,
                     )
                 } else {
                     o_ty
@@ -1058,7 +1060,11 @@ fn check_fn<'a, 'tcx>(
 
     let declared_ret_ty = fn_sig.output();
     fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-    let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(fn_id, &declared_ret_ty);
+    let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(
+        fn_id,
+        &declared_ret_ty,
+        decl.output.span(),
+    );
     fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
     fn_sig = fcx.tcx.mk_fn_sig(
         fn_sig.inputs().iter().cloned(),
@@ -1285,7 +1291,7 @@ fn check_fn<'a, 'tcx>(
     (fcx, gen_ty)
 }
 
-fn check_struct<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) {
+fn check_struct(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
     let def_id = tcx.hir().local_def_id_from_hir_id(id);
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
@@ -1299,7 +1305,7 @@ fn check_struct<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) {
     check_packed(tcx, span, def_id);
 }
 
-fn check_union<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) {
+fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
     let def_id = tcx.hir().local_def_id_from_hir_id(id);
     let def = tcx.adt_def(def_id);
     def.destructor(tcx); // force the destructor to be evaluated
@@ -1461,14 +1467,14 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
     }
 }
 
-fn check_on_unimplemented<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, item: &hir::Item) {
+fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item) {
     let item_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
     // an error would be reported if this fails.
     let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id);
 }
 
-fn report_forbidden_specialization<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn report_forbidden_specialization(
+    tcx: TyCtxt<'_>,
     impl_item: &hir::ImplItem,
     parent_impl: DefId,
 ) {
@@ -1684,7 +1690,7 @@ fn check_impl_items_against_trait<'tcx>(
 /// Checks whether a type can be represented in memory. In particular, it
 /// identifies types that contain themselves without indirection through a
 /// pointer, which would mean their size is unbounded.
-fn check_representable<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, item_def_id: DefId) -> bool {
+fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: DefId) -> bool {
     let rty = tcx.type_of(item_def_id);
 
     // Check that it is possible to represent this type. This call identifies
@@ -1706,7 +1712,7 @@ fn check_representable<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, item_def_id: DefId) ->
     return true;
 }
 
-pub fn check_simd<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
     let t = tcx.type_of(def_id);
     if let ty::Adt(def, substs) = t.sty {
         if def.is_struct() {
@@ -1735,7 +1741,7 @@ pub fn check_simd<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
     }
 }
 
-fn check_packed<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
     let repr = tcx.adt_def(def_id).repr;
     if repr.packed() {
         for attr in tcx.get_attrs(def_id).iter() {
@@ -1759,7 +1765,7 @@ fn check_packed<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
     }
 }
 
-fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
+fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
     let t = tcx.type_of(def_id);
     if stack.contains(&def_id) {
         debug!("check_packed_inner: {:?} is recursive", t);
@@ -1833,7 +1839,7 @@ fn bad_non_zero_sized_fields<'tcx>(
     err.emit();
 }
 
-fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
+fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
     let adt = tcx.adt_def(def_id);
     if !adt.repr.transparent() {
         return;
@@ -1982,7 +1988,7 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i
     check_transparent(tcx, sp, def_id);
 }
 
-fn report_unexpected_variant_res<'tcx>(tcx: TyCtxt<'tcx>, res: Res, span: Span, qpath: &QPath) {
+fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span, qpath: &QPath) {
     span_err!(tcx.sess, span, E0533,
               "expected unit struct/variant or constant, found {} `{}`",
               res.descr(),
@@ -2445,6 +2451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         parent_id: hir::HirId,
         value: &T,
+        value_span: Span,
     ) -> T {
         let parent_def_id = self.tcx.hir().local_def_id_from_hir_id(parent_id);
         debug!("instantiate_opaque_types_from_value(parent_def_id={:?}, value={:?})",
@@ -2457,6 +2464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.body_id,
                 self.param_env,
                 value,
+                value_span,
             )
         );
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 034ff5f8347..3aa144ca352 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, GenericParamDefKind, TypeFoldable, ToPredicate};
+use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::ConstValue;
@@ -68,7 +68,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
 /// We do this check as a pre-pass before checking fn bodies because if these constraints are
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
-pub fn check_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let item = tcx.hir().expect_item(hir_id);
 
@@ -156,7 +156,7 @@ pub fn check_item_well_formed<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
     }
 }
 
-pub fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let trait_item = tcx.hir().expect_trait_item(hir_id);
 
@@ -167,7 +167,7 @@ pub fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
     check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig);
 }
 
-pub fn check_impl_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let impl_item = tcx.hir().expect_impl_item(hir_id);
 
@@ -178,8 +178,8 @@ pub fn check_impl_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
     check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
 }
 
-fn check_associated_item<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn check_associated_item(
+    tcx: TyCtxt<'_>,
     item_id: hir::HirId,
     span: Span,
     sig_if_method: Option<&hir::MethodSig>,
@@ -231,7 +231,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) -> CheckWfFcxBuilder<'tcx
     for_id(tcx, item.hir_id, item.span)
 }
 
-fn for_id<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'tcx> {
+fn for_id(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) -> CheckWfFcxBuilder<'_> {
     let def_id = tcx.hir().local_def_id_from_hir_id(id);
     CheckWfFcxBuilder {
         inherited: Inherited::build(tcx, def_id),
@@ -261,14 +261,15 @@ fn check_type_defn<'tcx, F>(
             let needs_drop_copy = || {
                 packed && {
                     let ty = variant.fields.last().unwrap().ty;
-                    fcx.tcx.erase_regions(&ty).lift_to_tcx(fcx_tcx)
-                        .map(|ty| ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id)))
-                        .unwrap_or_else(|| {
+                    let ty = fcx.tcx.erase_regions(&ty);
+                    if ty.has_local_value() {
                             fcx_tcx.sess.delay_span_bug(
                                 item.span, &format!("inference variables in {:?}", ty));
                             // Just treat unresolved type expression as if it needs drop.
                             true
-                        })
+                    } else {
+                        ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
+                    }
                 }
             };
             let all_sized =
@@ -316,7 +317,7 @@ fn check_type_defn<'tcx, F>(
     });
 }
 
-fn check_trait<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
+fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item) {
     debug!("check_trait: {:?}", item.hir_id);
 
     let trait_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
@@ -339,7 +340,7 @@ fn check_trait<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
     });
 }
 
-fn check_item_fn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
+fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item) {
     for_item(tcx, item).with_fcx(|fcx, tcx| {
         let def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
         let sig = fcx.tcx.fn_sig(def_id);
@@ -351,8 +352,8 @@ fn check_item_fn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item) {
     })
 }
 
-fn check_item_type<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn check_item_type(
+    tcx: TyCtxt<'_>,
     item_id: hir::HirId,
     ty_span: Span,
     allow_foreign_ty: bool,
@@ -979,7 +980,7 @@ fn check_variances_for_type_defn<'tcx>(
     }
 }
 
-fn report_bivariance<'tcx>(tcx: TyCtxt<'tcx>, span: Span, param_name: ast::Name) {
+fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) {
     let mut err = error_392(tcx, span, param_name);
 
     let suggested_marker_id = tcx.lang_items().phantom_data();
@@ -1022,7 +1023,7 @@ fn reject_shadowing_parameters(tcx: TyCtxt<'_>, def_id: DefId) {
 
 /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
 /// aren't true.
-fn check_false_global_bounds<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, id: hir::HirId) {
+fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
     let empty_env = ty::ParamEnv::empty();
 
     let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);
@@ -1103,6 +1104,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id_from_hir_id(field.hir_id));
             let field_ty = self.normalize_associated_types_in(field.span,
                                                               &field_ty);
+            let field_ty = self.resolve_vars_if_possible(&field_ty);
+            debug!("non_enum_variant: type of field {:?} is {:?}", field, field_ty);
             AdtField { ty: field_ty, span: field.span }
         })
         .collect();
@@ -1134,11 +1137,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-fn error_392<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn error_392(
+    tcx: TyCtxt<'_>,
     span: Span,
     param_name: ast::Name,
-) -> DiagnosticBuilder<'tcx> {
+) -> DiagnosticBuilder<'_> {
     let mut err = struct_span_err!(tcx.sess, span, E0392,
                   "parameter `{}` is never used", param_name);
     err.span_label(span, "unused parameter");
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 6a95dec1c81..28711e32a4c 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -363,10 +363,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     }
 
     fn visit_free_region_map(&mut self) {
-        let free_region_map = self.tcx()
-            .lift_to_global(&self.fcx.tables.borrow().free_region_map);
-        let free_region_map = free_region_map.expect("all regions in free-region-map are global");
-        self.tables.free_region_map = free_region_map;
+        self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone();
+        debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value()));
     }
 
     fn visit_user_provided_tys(&mut self) {
@@ -381,12 +379,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 local_id,
             };
 
-            let c_ty = if let Some(c_ty) = self.tcx().lift_to_global(c_ty) {
-                c_ty
-            } else {
+            if cfg!(debug_assertions) && c_ty.has_local_value() {
                 span_bug!(
                     hir_id.to_span(self.fcx.tcx),
-                    "writeback: `{:?}` missing from the global type context",
+                    "writeback: `{:?}` is a local value",
                     c_ty
                 );
             };
@@ -423,12 +419,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
 
         for (&def_id, c_sig) in fcx_tables.user_provided_sigs.iter() {
-            let c_sig = if let Some(c_sig) = self.tcx().lift_to_global(c_sig) {
-                c_sig
-            } else {
+            if cfg!(debug_assertions) && c_sig.has_local_value() {
                 span_bug!(
                     self.fcx.tcx.hir().span_if_local(def_id).unwrap(),
-                    "writeback: `{:?}` missing from the global type context",
+                    "writeback: `{:?}` is a local value",
                     c_sig
                 );
             };
@@ -592,10 +586,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 }
             }
 
-            if let Some(substs) = self.tcx().lift_to_global(&opaque_defn.substs) {
+            if !opaque_defn.substs.has_local_value() {
                 let new = ty::ResolvedOpaqueTy {
                     concrete_type: definition_ty,
-                    substs,
+                    substs: opaque_defn.substs,
                 };
 
                 let old = self.tables
@@ -617,7 +611,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             } else {
                 self.tcx().sess.delay_span_bug(
                     span,
-                    "cannot lift `opaque_defn` substs to global type context",
+                    "`opaque_defn` is a local value",
                 );
             }
         }
@@ -743,20 +737,19 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T::Lifted
+    fn resolve<T>(&self, x: &T, span: &dyn Locatable) -> T
     where
-        T: TypeFoldable<'tcx> + ty::Lift<'tcx>,
+        T: TypeFoldable<'tcx>,
     {
         let x = x.fold_with(&mut Resolver::new(self.fcx, span, self.body));
-        if let Some(lifted) = self.tcx().lift_to_global(&x) {
-            lifted
-        } else {
+        if cfg!(debug_assertions) && x.has_local_value() {
             span_bug!(
                 span.to_span(self.fcx.tcx),
-                "writeback: `{:?}` missing from the global type context",
+                "writeback: `{:?}` is a local value",
                 x
             );
         }
+        x
     }
 }
 
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 7e781eeec56..8614de19770 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -13,7 +13,7 @@ use rustc::util::nodemap::DefIdSet;
 
 use rustc_data_structures::fx::FxHashMap;
 
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports = DefIdSet::default();
     for &body_id in tcx.hir().krate().bodies.keys() {
         let item_def_id = tcx.hir().body_owner_def_id(body_id);
@@ -70,7 +70,7 @@ impl CheckVisitor<'tcx> {
     }
 }
 
-fn unused_crates_lint<'tcx>(tcx: TyCtxt<'tcx>) {
+fn unused_crates_lint(tcx: TyCtxt<'_>) {
     let lint = lint::builtin::UNUSED_EXTERN_CRATES;
 
     // Collect first the crates that are completely unused.  These we
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index 42deeaf31f4..68bdcbfe3fd 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId;
 use hir::Node;
 use rustc::hir::{self, ItemKind};
 
-pub fn check_trait<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) {
+pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
         .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
@@ -46,7 +46,7 @@ impl<'tcx> Checker<'tcx> {
     }
 }
 
-fn visit_implementation_of_drop<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) {
     if let ty::Adt(..) = tcx.type_of(impl_did).sty {
         /* do nothing */
     } else {
@@ -74,7 +74,7 @@ fn visit_implementation_of_drop<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
     }
 }
 
-fn visit_implementation_of_copy<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) {
     debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
 
     let impl_hir_id = if let Some(n) = tcx.hir().as_local_hir_id(impl_did) {
@@ -154,7 +154,7 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: DefId) {
     }
 }
 
-fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) {
+fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) {
     debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
            impl_did);
     if impl_did.is_local() {
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 6088c03fc06..9efe1273ac0 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -7,7 +7,6 @@
 //! `tcx.inherent_impls(def_id)`). That value, however,
 //! is computed by selecting an idea from this table.
 
-use rustc::dep_graph::DepKind;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -17,10 +16,10 @@ use syntax::ast;
 use syntax_pos::Span;
 
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
-pub fn crate_inherent_impls<'tcx>(
-    tcx: TyCtxt<'tcx>,
+pub fn crate_inherent_impls(
+    tcx: TyCtxt<'_>,
     crate_num: CrateNum,
-) -> &'tcx CrateInherentImpls {
+) -> &CrateInherentImpls {
     assert_eq!(crate_num, LOCAL_CRATE);
 
     let krate = tcx.hir().krate();
@@ -33,38 +32,14 @@ pub fn crate_inherent_impls<'tcx>(
 }
 
 /// On-demand query: yields a vector of the inherent impls for a specific type.
-pub fn inherent_impls<'tcx>(tcx: TyCtxt<'tcx>, ty_def_id: DefId) -> &'tcx [DefId] {
+pub fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: DefId) -> &[DefId] {
     assert!(ty_def_id.is_local());
 
-    // NB. Until we adopt the red-green dep-tracking algorithm (see
-    // [the plan] for details on that), we do some hackery here to get
-    // the dependencies correct.  Basically, we use a `with_ignore` to
-    // read the result we want. If we didn't have the `with_ignore`,
-    // we would wind up with a dependency on the entire crate, which
-    // we don't want. Then we go and add dependencies on all the impls
-    // in the result (which is what we wanted).
-    //
-    // The result is a graph with an edge from `Hir(I)` for every impl
-    // `I` defined on some type `T` to `CoherentInherentImpls(T)`,
-    // thus ensuring that if any of those impls change, the set of
-    // inherent impls is considered dirty.
-    //
-    // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4
-
-    let result = tcx.dep_graph.with_ignore(|| {
-        let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
-        match crate_map.inherent_impls.get(&ty_def_id) {
-            Some(v) => &v[..],
-            None => &[],
-        }
-    });
-
-    for &impl_def_id in &result[..] {
-        let def_path_hash = tcx.def_path_hash(impl_def_id);
-        tcx.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+    let crate_map = tcx.crate_inherent_impls(ty_def_id.krate);
+    match crate_map.inherent_impls.get(&ty_def_id) {
+        Some(v) => &v[..],
+        None => &[],
     }
-
-    result
 }
 
 struct InherentCollect<'tcx> {
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
index aae1b1777a3..1785304fb1d 100644
--- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs
+++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
@@ -5,7 +5,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::traits::{self, IntercrateMode};
 use rustc::ty::TyCtxt;
 
-pub fn crate_inherent_impls_overlap_check<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) {
+pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     assert_eq!(crate_num, LOCAL_CRATE);
     let krate = tcx.hir().krate();
     krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 4336e861ce2..9b9789139b7 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -18,7 +18,7 @@ mod inherent_impls_overlap;
 mod orphan;
 mod unsafety;
 
-fn check_impl<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
+fn check_impl(tcx: TyCtxt<'_>, hir_id: HirId) {
     let impl_def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
 
     // If there are no traits, then this implementation must have a
@@ -124,7 +124,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn coherent_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
+fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
     let impls = tcx.hir().trait_impls(def_id);
     for &impl_id in impls {
         check_impl(tcx, impl_id);
@@ -135,7 +135,7 @@ fn coherent_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) {
     builtin::check_trait(tcx, def_id);
 }
 
-pub fn check_coherence<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check_coherence(tcx: TyCtxt<'_>) {
     for &trait_def_id in tcx.hir().krate().trait_impls.keys() {
         tcx.ensure().coherent_trait(trait_def_id);
     }
@@ -151,7 +151,7 @@ pub fn check_coherence<'tcx>(tcx: TyCtxt<'tcx>) {
 /// Overlap: no two impls for the same trait are implemented for the
 /// same type. Likewise, no two inherent impls for a given type
 /// constructor provide a method with the same name.
-fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) {
+fn check_impl_overlap(tcx: TyCtxt<'_>, hir_id: HirId) {
     let impl_def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
     let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
     let trait_def_id = trait_ref.def_id;
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 4e6fcfe0593..2d0faecd8ee 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -6,7 +6,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir;
 
-pub fn check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check(tcx: TyCtxt<'_>) {
     let mut orphan = OrphanChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut orphan);
 }
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index c41a0e1514e..123d7c6123b 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -5,7 +5,7 @@ use rustc::ty::TyCtxt;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::{self, Unsafety};
 
-pub fn check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn check(tcx: TyCtxt<'_>) {
     let mut unsafety = UnsafetyChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut unsafety);
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 87e1166b7c0..e5802179ec4 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -56,7 +56,7 @@ struct OnlySelfBounds(bool);
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
 
-fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
         &mut CollectItemTypesVisitor { tcx }.as_deep_visitor()
@@ -253,10 +253,10 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
     }
 }
 
-fn type_param_predicates<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn type_param_predicates(
+    tcx: TyCtxt<'_>,
     (item_def_id, def_id): (DefId, DefId),
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
     use rustc::hir::*;
 
     // In the AST, bounds can derive from two places. Either
@@ -381,7 +381,7 @@ impl ItemCtxt<'tcx> {
 /// parameter with ID `param_id`. We use this so as to avoid running
 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
 /// conversion of the type to avoid inducing unnecessary cycles.
-fn is_param<'tcx>(tcx: TyCtxt<'tcx>, ast_ty: &hir::Ty, param_id: hir::HirId) -> bool {
+fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty, param_id: hir::HirId) -> bool {
     if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
         match path.res {
             Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => {
@@ -394,7 +394,7 @@ fn is_param<'tcx>(tcx: TyCtxt<'tcx>, ast_ty: &hir::Ty, param_id: hir::HirId) ->
     }
 }
 
-fn convert_item<'tcx>(tcx: TyCtxt<'tcx>, item_id: hir::HirId) {
+fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
     let it = tcx.hir().expect_item(item_id);
     debug!("convert: item {} with id {}", it.ident, it.hir_id);
     let def_id = tcx.hir().local_def_id_from_hir_id(item_id);
@@ -476,7 +476,7 @@ fn convert_item<'tcx>(tcx: TyCtxt<'tcx>, item_id: hir::HirId) {
     }
 }
 
-fn convert_trait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_id: hir::HirId) {
+fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
     let trait_item = tcx.hir().expect_trait_item(trait_item_id);
     let def_id = tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
     tcx.generics_of(def_id);
@@ -497,7 +497,7 @@ fn convert_trait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_id: hir::HirId) {
     tcx.predicates_of(def_id);
 }
 
-fn convert_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item_id: hir::HirId) {
+fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
     let def_id = tcx.hir().local_def_id_from_hir_id(impl_item_id);
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
@@ -507,7 +507,7 @@ fn convert_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item_id: hir::HirId) {
     }
 }
 
-fn convert_variant_ctor<'tcx>(tcx: TyCtxt<'tcx>, ctor_id: hir::HirId) {
+fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) {
     let def_id = tcx.hir().local_def_id_from_hir_id(ctor_id);
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
@@ -562,8 +562,8 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants:
     }
 }
 
-fn convert_variant<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn convert_variant(
+    tcx: TyCtxt<'_>,
     variant_did: Option<DefId>,
     ctor_did: Option<DefId>,
     ident: Ident,
@@ -619,7 +619,7 @@ fn convert_variant<'tcx>(
     )
 }
 
-fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
+fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
     use rustc::hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -686,10 +686,10 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AdtDef {
 /// Ensures that the super-predicates of the trait with a `DefId`
 /// of `trait_def_id` are converted and stored. This also ensures that
 /// the transitive super-predicates are converted.
-fn super_predicates_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn super_predicates_of(
+    tcx: TyCtxt<'_>,
     trait_def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
     let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap();
 
@@ -740,7 +740,7 @@ fn super_predicates_of<'tcx>(
     })
 }
 
-fn trait_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::TraitDef {
+fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     let item = tcx.hir().expect_item(hir_id);
 
@@ -879,7 +879,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 }
 
-fn generics_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::Generics {
+fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
     use rustc::hir::*;
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -1122,7 +1122,7 @@ fn generics_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::Generics {
     })
 }
 
-fn report_assoc_ty_on_inherent_impl<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
+fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) {
     span_err!(
         tcx.sess,
         span,
@@ -1131,7 +1131,7 @@ fn report_assoc_ty_on_inherent_impl<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
     );
 }
 
-fn type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     checked_type_of(tcx, def_id, true).unwrap()
 }
 
@@ -1139,7 +1139,7 @@ fn type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
 ///
 /// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
 /// you'd better just call [`type_of`] directly.
-pub fn checked_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fail: bool) -> Option<Ty<'tcx>> {
+pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty<'_>> {
     use rustc::hir::*;
 
     let hir_id = match tcx.hir().as_local_hir_id(def_id) {
@@ -1353,7 +1353,7 @@ pub fn checked_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fail: bool) -> Op
                                 None
                             }
                         }
-                        Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path),
+                        Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(&**path),
                         _ => None,
                     };
 
@@ -1464,7 +1464,7 @@ pub fn checked_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fail: bool) -> Op
     })
 }
 
-fn find_existential_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+fn find_existential_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     use rustc::hir::{ImplItem, Item, TraitItem};
 
     debug!("find_existential_constraints({:?})", def_id);
@@ -1682,7 +1682,7 @@ fn find_existential_constraints<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'t
     }
 }
 
-fn fn_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
     use rustc::hir::*;
     use rustc::hir::Node::*;
 
@@ -1758,7 +1758,7 @@ fn fn_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::PolyFnSig<'tcx> {
     }
 }
 
-fn impl_trait_ref<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::TraitRef<'tcx>> {
+fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -1773,7 +1773,7 @@ fn impl_trait_ref<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<ty::TraitRef
     }
 }
 
-fn impl_polarity<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> hir::ImplPolarity {
+fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     match tcx.hir().expect_item(hir_id).node {
         hir::ItemKind::Impl(_, polarity, ..) => polarity,
@@ -1804,10 +1804,10 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
 /// Returns a list of type predicates for the definition with ID `def_id`, including inferred
 /// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
 /// inferred constraints concerning which regions outlive other regions.
-fn predicates_defined_on<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn predicates_defined_on(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
     debug!("predicates_defined_on({:?})", def_id);
     let mut result = tcx.explicit_predicates_of(def_id);
     debug!(
@@ -1834,7 +1834,7 @@ fn predicates_defined_on<'tcx>(
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
 /// `Self: Trait` predicates for traits.
-fn predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::GenericPredicates<'tcx> {
+fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> {
     let mut result = tcx.predicates_defined_on(def_id);
 
     if tcx.is_trait(def_id) {
@@ -1861,10 +1861,10 @@ fn predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::GenericPre
 
 /// Returns a list of user-specified type predicates for the definition with ID `def_id`.
 /// N.B., this does not include any implied/inferred constraints.
-fn explicit_predicates_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn explicit_predicates_of(
+    tcx: TyCtxt<'_>,
     def_id: DefId,
-) -> &'tcx ty::GenericPredicates<'tcx> {
+) -> &ty::GenericPredicates<'_> {
     use rustc::hir::*;
     use rustc_data_structures::fx::FxHashSet;
 
@@ -2271,7 +2271,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     fty
 }
 
-fn is_foreign_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+fn is_foreign_item(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     match tcx.hir().get_if_local(def_id) {
         Some(Node::ForeignItem(..)) => true,
         Some(_) => false,
@@ -2279,7 +2279,7 @@ fn is_foreign_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
     }
 }
 
-fn static_mutability<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<hir::Mutability> {
+fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option<hir::Mutability> {
     match tcx.hir().get_if_local(def_id) {
         Some(Node::Item(&hir::Item {
             node: hir::ItemKind::Static(_, mutbl, _), ..
@@ -2387,7 +2387,7 @@ fn from_target_feature(
     }
 }
 
-fn linkage_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Linkage {
+fn linkage_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Linkage {
     use rustc::mir::mono::Linkage::*;
 
     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
@@ -2422,7 +2422,7 @@ fn linkage_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Linkag
     }
 }
 
-fn codegen_fn_attrs<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> CodegenFnAttrs {
+fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     let attrs = tcx.get_attrs(id);
 
     let mut codegen_fn_attrs = CodegenFnAttrs::new();
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index b833d8555ee..08c7cbc389a 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -49,7 +49,7 @@ use syntax_pos::Span;
 /// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
 /// //   ^ 'a is unused and appears in assoc type, error
 /// ```
-pub fn impl_wf_check<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn impl_wf_check(tcx: TyCtxt<'_>) {
     // We will tag this as part of the WF check -- logically, it is,
     // but it's one that we must perform earlier than the rest of
     // WfCheck.
@@ -58,7 +58,7 @@ pub fn impl_wf_check<'tcx>(tcx: TyCtxt<'tcx>) {
     }
 }
 
-fn check_mod_impl_wf<'tcx>(tcx: TyCtxt<'tcx>, module_def_id: DefId) {
+fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(
         module_def_id,
         &mut ImplWfCheck { tcx }
@@ -92,8 +92,8 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { }
 }
 
-fn enforce_impl_params_are_constrained<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn enforce_impl_params_are_constrained(
+    tcx: TyCtxt<'_>,
     impl_def_id: DefId,
     impl_item_refs: &[hir::ImplItemRef],
 ) {
@@ -183,7 +183,7 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: &str)
 }
 
 /// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct<'tcx>(tcx: TyCtxt<'tcx>, impl_item_refs: &[hir::ImplItemRef]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
     let mut seen_type_items = FxHashMap::default();
     let mut seen_value_items = FxHashMap::default();
     for impl_item_ref in impl_item_refs {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 182594e7684..88e6c0f579e 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -69,6 +69,7 @@ This API is completely unstable and subject to change.
 #![feature(slice_patterns)]
 #![feature(never_type)]
 #![feature(inner_deref)]
+#![feature(mem_take)]
 
 #![recursion_limit="256"]
 
@@ -105,7 +106,7 @@ use rustc::lint;
 use rustc::middle;
 use rustc::session;
 use rustc::util::common::ErrorReported;
-use rustc::session::config::{EntryFnType, nightly_options};
+use rustc::session::config::EntryFnType;
 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -124,21 +125,6 @@ pub struct TypeAndSubsts<'tcx> {
     ty: Ty<'tcx>,
 }
 
-fn check_type_alias_enum_variants_enabled<'tcx>(tcx: TyCtxt<'tcx>, span: Span) {
-    if !tcx.features().type_alias_enum_variants {
-        let mut err = tcx.sess.struct_span_err(
-            span,
-            "enum variants on type aliases are experimental"
-        );
-        if nightly_options::is_nightly_build() {
-            help!(&mut err,
-                "add `#![feature(type_alias_enum_variants)]` to the \
-                crate attributes to enable");
-        }
-        err.emit();
-    }
-}
-
 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl, abi: Abi, span: Span) {
     if decl.c_variadic && !(abi == Abi::C || abi == Abi::Cdecl) {
         let mut err = struct_span_err!(tcx.sess, span, E0045,
@@ -176,7 +162,7 @@ fn require_same_types<'tcx>(
     })
 }
 
-fn check_main_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, main_def_id: DefId) {
+fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
     let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap();
     let main_span = tcx.def_span(main_def_id);
     let main_t = tcx.type_of(main_def_id);
@@ -241,7 +227,7 @@ fn check_main_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, main_def_id: DefId) {
     }
 }
 
-fn check_start_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, start_def_id: DefId) {
+fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
     let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap();
     let start_span = tcx.def_span(start_def_id);
     let start_t = tcx.type_of(start_def_id);
@@ -298,7 +284,7 @@ fn check_start_fn_ty<'tcx>(tcx: TyCtxt<'tcx>, start_def_id: DefId) {
     }
 }
 
-fn check_for_entry_fn<'tcx>(tcx: TyCtxt<'tcx>) {
+fn check_for_entry_fn(tcx: TyCtxt<'_>) {
     match tcx.entry_fn(LOCAL_CRATE) {
         Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
         Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
@@ -315,7 +301,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     impl_wf_check::provide(providers);
 }
 
-pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) -> Result<(), ErrorReported> {
+pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
     tcx.sess.profiler(|p| p.start_activity("type-check crate"));
 
     // this ensures that later parts of type checking can assume that items
diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs
index 63e41e01fbf..6b8f6fccd40 100644
--- a/src/librustc_typeck/outlives/mod.rs
+++ b/src/librustc_typeck/outlives/mod.rs
@@ -20,10 +20,10 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn inferred_outlives_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn inferred_outlives_of(
+    tcx: TyCtxt<'_>,
     item_def_id: DefId,
-) -> &'tcx [ty::Predicate<'tcx>] {
+) -> &[ty::Predicate<'_>] {
     let id = tcx
         .hir()
         .as_local_hir_id(item_def_id)
@@ -70,10 +70,10 @@ fn inferred_outlives_of<'tcx>(
     }
 }
 
-fn inferred_outlives_crate<'tcx>(
-    tcx: TyCtxt<'tcx>,
+fn inferred_outlives_crate(
+    tcx: TyCtxt<'_>,
     crate_num: CrateNum,
-) -> &'tcx CratePredicatesMap<'tcx> {
+) -> &CratePredicatesMap<'_> {
     assert_eq!(crate_num, LOCAL_CRATE);
 
     // Compute a map from each struct/enum/union S to the **explicit**
diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs
index 4690cb9eada..5ddf95b0f80 100644
--- a/src/librustc_typeck/outlives/test.rs
+++ b/src/librustc_typeck/outlives/test.rs
@@ -3,7 +3,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
 use syntax::symbol::sym;
 
-pub fn test_inferred_outlives<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
     tcx.hir()
        .krate()
        .visit_all_item_likes(&mut OutlivesTest { tcx });
diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs
index c6b0da3fe47..783890da639 100644
--- a/src/librustc_typeck/outlives/utils.rs
+++ b/src/librustc_typeck/outlives/utils.rs
@@ -125,7 +125,7 @@ pub fn insert_outlives_predicate<'tcx>(
     }
 }
 
-fn is_free_region<'tcx>(tcx: TyCtxt<'tcx>, region: Region<'_>) -> bool {
+fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool {
     // First, screen for regions that might appear in a type header.
     match region {
         // These correspond to `T: 'a` relationships:
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 1a8871a3da9..343d7ea656f 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -34,7 +34,7 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
 }
 
-fn crate_variances<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx CrateVariancesMap<'tcx> {
+fn crate_variances(tcx: TyCtxt<'_>, crate_num: CrateNum) -> &CrateVariancesMap<'_> {
     assert_eq!(crate_num, LOCAL_CRATE);
     let mut arena = arena::TypedArena::default();
     let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
@@ -42,7 +42,7 @@ fn crate_variances<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx CrateV
     tcx.arena.alloc(solve::solve_constraints(constraints_cx))
 }
 
-fn variances_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> &'tcx [ty::Variance] {
+fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
     let id = tcx.hir().as_local_hir_id(item_def_id).expect("expected local def-id");
     let unsupported = || {
         // Variance not relevant.
diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs
index cefc200f5cb..0c7ebc34e8f 100644
--- a/src/librustc_typeck/variance/test.rs
+++ b/src/librustc_typeck/variance/test.rs
@@ -3,7 +3,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::ty::TyCtxt;
 use syntax::symbol::sym;
 
-pub fn test_variance<'tcx>(tcx: TyCtxt<'tcx>) {
+pub fn test_variance(tcx: TyCtxt<'_>) {
     tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx });
 }
 
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 67113787915..ad211763a6c 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -16,7 +16,7 @@ use syntax_pos::Span;
 
 use crate::html::escape::Escape;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum Cfg {
     /// Accepts all configurations.
     True,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 41a56756a14..8ae96d86657 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,6 +20,7 @@ use rustc::mir::interpret::{GlobalId, ConstValue};
 use rustc::hir;
 use rustc::hir::def::{CtorKind, DefKind, Res};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::ptr::P;
 use rustc::ty::subst::{InternalSubsts, SubstsRef, UnpackedKind};
 use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind};
 use rustc::ty::fold::TypeFolder;
@@ -29,7 +30,6 @@ use syntax::ast::{self, AttrStyle, Ident};
 use syntax::attr;
 use syntax::ext::base::MacroKind;
 use syntax::source_map::{dummy_spanned, Spanned};
-use syntax::ptr::P;
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::symbol::InternedString;
 use syntax_pos::{self, Pos, FileName};
@@ -223,7 +223,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct ExternalCrate {
     pub name: String,
     pub src: FileName,
@@ -355,7 +355,7 @@ impl Clean<ExternalCrate> for CrateNum {
 /// Anything with a source location and set of attributes and, optionally, a
 /// name. That is, anything that can be documented. This doesn't correspond
 /// directly to the AST's concept of an item; it's a strict superset.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone)]
 pub struct Item {
     /// Stringified span
     pub source: Span,
@@ -528,7 +528,7 @@ impl Item {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub enum ItemEnum {
     ExternCrateItem(String, Option<String>),
     ImportItem(Import),
@@ -594,7 +594,7 @@ impl ItemEnum {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Module {
     pub items: Vec<Item>,
     pub is_crate: bool,
@@ -731,7 +731,7 @@ impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
 /// Included files are kept separate from inline doc comments so that proper line-number
 /// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
 /// kept separate because of issue #42760.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum DocFragment {
     /// A doc fragment created from a `///` or `//!` doc comment.
     SugaredDoc(usize, syntax_pos::Span, String),
@@ -781,7 +781,7 @@ impl<'a> FromIterator<&'a DocFragment> for String {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Debug, Default)]
 pub struct Attributes {
     pub doc_strings: Vec<DocFragment>,
     pub other_attrs: Vec<ast::Attribute>,
@@ -1048,7 +1048,7 @@ impl Clean<Attributes> for [ast::Attribute] {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum GenericBound {
     TraitBound(PolyTrait, hir::TraitBoundModifier),
     Outlives(Lifetime),
@@ -1231,7 +1231,7 @@ impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Lifetime(String);
 
 impl Lifetime {
@@ -1326,7 +1326,7 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
@@ -1464,7 +1464,7 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum GenericParamDefKind {
     Lifetime,
     Type {
@@ -1498,7 +1498,7 @@ impl GenericParamDefKind {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct GenericParamDef {
     pub name: String,
 
@@ -1610,7 +1610,7 @@ impl Clean<GenericParamDef> for hir::GenericParam {
 }
 
 // maybe use a Generic enum and use Vec<Generic>?
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
 pub struct Generics {
     pub params: Vec<GenericParamDef>,
     pub where_predicates: Vec<WherePredicate>,
@@ -1874,7 +1874,7 @@ pub fn get_all_types(
     (all_types.into_iter().collect(), ret_types)
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Method {
     pub generics: Generics,
     pub decl: FnDecl,
@@ -1902,7 +1902,7 @@ impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct TyMethod {
     pub header: hir::FnHeader,
     pub decl: FnDecl,
@@ -1911,7 +1911,7 @@ pub struct TyMethod {
     pub ret_types: Vec<Type>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
@@ -1952,7 +1952,7 @@ impl Clean<Item> for doctree::Function<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct FnDecl {
     pub inputs: Arguments,
     pub output: FunctionRetTy,
@@ -1989,7 +1989,7 @@ impl FnDecl {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Arguments {
     pub values: Vec<Argument>,
 }
@@ -2063,13 +2063,13 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Argument {
     pub type_: Type,
     pub name: String,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Debug)]
 pub enum SelfTy {
     SelfValue,
     SelfBorrowed(Option<Lifetime>, Mutability),
@@ -2093,7 +2093,7 @@ impl Argument {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum FunctionRetTy {
     Return(Type),
     DefaultReturn,
@@ -2117,7 +2117,7 @@ impl GetDefId for FunctionRetTy {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Trait {
     pub auto: bool,
     pub unsafety: hir::Unsafety,
@@ -2153,7 +2153,7 @@ impl Clean<Item> for doctree::Trait<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct TraitAlias {
     pub generics: Generics,
     pub bounds: Vec<GenericBound>,
@@ -2437,7 +2437,7 @@ impl Clean<Item> for ty::AssocItem {
 }
 
 /// A trait reference, which may have higher ranked lifetimes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct PolyTrait {
     pub trait_: Type,
     pub generic_params: Vec<GenericParamDef>,
@@ -2446,7 +2446,7 @@ pub struct PolyTrait {
 /// A representation of a type suitable for hyperlinking purposes. Ideally, one can get the original
 /// type out of the AST/`TyCtxt` given one of these, if more information is needed. Most
 /// importantly, it does not preserve mutability or boxes.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum Type {
     /// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
     ResolvedPath {
@@ -2469,7 +2469,6 @@ pub enum Type {
     Array(Box<Type>, String),
     Never,
     CVarArgs,
-    Unique(Box<Type>),
     RawPointer(Mutability, Box<Type>),
     BorrowedRef {
         lifetime: Option<Lifetime>,
@@ -2491,7 +2490,7 @@ pub enum Type {
     ImplTrait(Vec<GenericBound>),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
 pub enum PrimitiveType {
     Isize, I8, I16, I32, I64, I128,
     Usize, U8, U16, U32, U64, U128,
@@ -2510,7 +2509,7 @@ pub enum PrimitiveType {
     CVarArgs,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
+#[derive(Clone, Copy, Debug)]
 pub enum TypeKind {
     Enum,
     Function,
@@ -2520,7 +2519,6 @@ pub enum TypeKind {
     Struct,
     Union,
     Trait,
-    Variant,
     Typedef,
     Foreign,
     Macro,
@@ -3190,7 +3188,7 @@ impl Clean<Item> for ty::FieldDef {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub enum Visibility {
     Public,
     Inherited,
@@ -3219,7 +3217,7 @@ impl Clean<Option<Visibility>> for ty::Visibility {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Struct {
     pub struct_type: doctree::StructType,
     pub generics: Generics,
@@ -3227,7 +3225,7 @@ pub struct Struct {
     pub fields_stripped: bool,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Union {
     pub struct_type: doctree::StructType,
     pub generics: Generics,
@@ -3278,7 +3276,7 @@ impl Clean<Item> for doctree::Union<'_> {
 /// This is a more limited form of the standard Struct, different in that
 /// it lacks the things most items have (name, id, parameterization). Found
 /// only as a variant in an enum.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct VariantStruct {
     pub struct_type: doctree::StructType,
     pub fields: Vec<Item>,
@@ -3295,7 +3293,7 @@ impl Clean<VariantStruct> for ::rustc::hir::VariantData {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Enum {
     pub variants: IndexVec<VariantIdx, Item>,
     pub generics: Generics,
@@ -3321,7 +3319,7 @@ impl Clean<Item> for doctree::Enum<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Variant {
     pub kind: VariantKind,
 }
@@ -3384,7 +3382,7 @@ impl Clean<Item> for ty::VariantDef {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub enum VariantKind {
     CLike,
     Tuple(Vec<Type>),
@@ -3402,7 +3400,7 @@ impl Clean<VariantKind> for hir::VariantData {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Span {
     pub filename: FileName,
     pub loline: usize,
@@ -3448,7 +3446,7 @@ impl Clean<Span> for syntax_pos::Span {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct Path {
     pub global: bool,
     pub res: Res,
@@ -3471,7 +3469,7 @@ impl Clean<Path> for hir::Path {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum GenericArg {
     Lifetime(Lifetime),
     Type(Type),
@@ -3488,7 +3486,7 @@ impl fmt::Display for GenericArg {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum GenericArgs {
     AngleBracketed {
         args: Vec<GenericArg>,
@@ -3528,7 +3526,7 @@ impl Clean<GenericArgs> for hir::GenericArgs {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct PathSegment {
     pub name: String,
     pub args: GenericArgs,
@@ -3553,7 +3551,6 @@ fn strip_type(ty: Type) -> Type {
         }
         Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
         Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
-        Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
         Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
         Type::BorrowedRef { lifetime, mutability, type_ } => {
             Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
@@ -3625,7 +3622,7 @@ impl Clean<String> for InternedString {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Typedef {
     pub type_: Type,
     pub generics: Generics,
@@ -3649,7 +3646,7 @@ impl Clean<Item> for doctree::Typedef<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Existential {
     pub bounds: Vec<GenericBound>,
     pub generics: Generics,
@@ -3673,7 +3670,7 @@ impl Clean<Item> for doctree::Existential<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct BareFunctionDecl {
     pub unsafety: hir::Unsafety,
     pub generic_params: Vec<GenericParamDef>,
@@ -3695,7 +3692,7 @@ impl Clean<BareFunctionDecl> for hir::BareFnTy {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Static {
     pub type_: Type,
     pub mutability: Mutability,
@@ -3725,7 +3722,7 @@ impl Clean<Item> for doctree::Static<'_> {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Constant {
     pub type_: Type,
     pub expr: String,
@@ -3749,7 +3746,7 @@ impl Clean<Item> for doctree::Constant<'_> {
     }
 }
 
-#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
 pub enum Mutability {
     Mutable,
     Immutable,
@@ -3764,7 +3761,7 @@ impl Clean<Mutability> for hir::Mutability {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Copy, Debug, Hash)]
 pub enum ImplPolarity {
     Positive,
     Negative,
@@ -3779,7 +3776,7 @@ impl Clean<ImplPolarity> for hir::ImplPolarity {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Impl {
     pub unsafety: hir::Unsafety,
     pub generics: Generics,
@@ -4003,7 +4000,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub enum Import {
     // use source as str;
     Simple(String, ImportSource),
@@ -4011,7 +4008,7 @@ pub enum Import {
     Glob(ImportSource)
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct ImportSource {
     pub path: Path,
     pub did: Option<DefId>,
@@ -4227,7 +4224,7 @@ fn resolve_use_source(cx: &DocContext<'_>, path: Path) -> ImportSource {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Macro {
     pub source: String,
     pub imported_from: Option<String>,
@@ -4256,7 +4253,7 @@ impl Clean<Item> for doctree::Macro<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct ProcMacro {
     pub kind: MacroKind,
     pub helpers: Vec<String>,
@@ -4280,7 +4277,7 @@ impl Clean<Item> for doctree::ProcMacro<'_> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Stability {
     pub level: stability::StabilityLevel,
     pub feature: Option<String>,
@@ -4290,7 +4287,7 @@ pub struct Stability {
     pub issue: Option<u32>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Debug)]
 pub struct Deprecation {
     pub since: Option<String>,
     pub note: Option<String>,
@@ -4340,13 +4337,13 @@ impl Clean<Deprecation> for attr::Deprecation {
 
 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
 /// `A: Send + Sync` in `Foo<A: Send + Sync>`).
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct TypeBinding {
     pub name: String,
     pub kind: TypeBindingKind,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub enum TypeBindingKind {
     Equality {
         ty: Type,
@@ -4411,7 +4408,7 @@ pub fn enter_impl_trait<F, R>(cx: &DocContext<'_>, f: F) -> R
 where
     F: FnOnce() -> R,
 {
-    let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default());
+    let old_bounds = mem::take(&mut *cx.impl_trait_bounds.borrow_mut());
     let r = f();
     assert!(cx.impl_trait_bounds.borrow().is_empty());
     *cx.impl_trait_bounds.borrow_mut() = old_bounds;
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 36e6a6003df..e4fba73b820 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -131,7 +131,7 @@ pub fn ty_params(mut params: Vec<clean::GenericParamDef>) -> Vec<clean::GenericP
     for param in &mut params {
         match param.kind {
             clean::GenericParamDefKind::Type { ref mut bounds, .. } => {
-                *bounds = ty_bounds(mem::replace(bounds, Vec::new()));
+                *bounds = ty_bounds(mem::take(bounds));
             }
             _ => panic!("expected only type parameters"),
         }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 6b490f730af..67ca7f407d8 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -351,9 +351,6 @@ impl Options {
                             .unwrap_or_else(|| PathBuf::from("doc"));
         let mut cfgs = matches.opt_strs("cfg");
         cfgs.push("rustdoc".to_string());
-        if should_test {
-            cfgs.push("test".to_string());
-        }
 
         let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));
 
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 51deb4e9b97..45a3c8a3c22 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -6,11 +6,11 @@ use syntax::ast;
 use syntax::ast::{Name, NodeId};
 use syntax::attr;
 use syntax::ext::base::MacroKind;
-use syntax::ptr::P;
 use syntax_pos::{self, Span};
 
 use rustc::hir;
 use rustc::hir::def_id::CrateNum;
+use rustc::hir::ptr::P;
 
 pub struct Module<'hir> {
     pub name: Option<Name>,
@@ -78,7 +78,7 @@ impl Module<'hir> {
     }
 }
 
-#[derive(Debug, Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Debug, Clone, Copy)]
 pub enum StructType {
     /// A braced struct
     Plain,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index fa3bc3f5f4f..9e5cc03b831 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -737,9 +737,6 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
                 }
             }
         }
-        clean::Unique(..) => {
-            panic!("should have been cleaned")
-        }
     }
 }
 
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index 3f3f4c85e81..5f1a1b31616 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -110,7 +110,6 @@ impl From<clean::TypeKind> for ItemType {
             clean::TypeKind::Module     => ItemType::Module,
             clean::TypeKind::Static     => ItemType::Static,
             clean::TypeKind::Const      => ItemType::Constant,
-            clean::TypeKind::Variant    => ItemType::Variant,
             clean::TypeKind::Typedef    => ItemType::Typedef,
             clean::TypeKind::Foreign    => ItemType::ForeignType,
             clean::TypeKind::Macro      => ItemType::Macro,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f0aff961c67..2d6503c9445 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -660,7 +660,7 @@ pub fn run(mut krate: clean::Crate,
         deref_trait_did,
         deref_mut_trait_did,
         owned_box_did,
-        masked_crates: mem::replace(&mut krate.masked_crates, Default::default()),
+        masked_crates: mem::take(&mut krate.masked_crates),
         param_names: external_param_names,
         aliases: Default::default(),
     };
@@ -5188,9 +5188,6 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
             clean::Type::Array(ty, _) => {
                 work.push_back(*ty);
             },
-            clean::Type::Unique(ty) => {
-                work.push_back(*ty);
-            },
             clean::Type::RawPointer(_, ty) => {
                 work.push_back(*ty);
             },
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7a8b088020c..342264db43c 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -21,6 +21,7 @@
 #![feature(drain_filter)]
 #![feature(inner_deref)]
 #![feature(never_type)]
+#![feature(mem_take)]
 
 #![recursion_limit="256"]
 
@@ -42,8 +43,6 @@ extern crate test as testing;
 #[macro_use] extern crate log;
 extern crate rustc_errors as errors;
 
-extern crate serialize as rustc_serialize; // used by deriving
-
 use std::default::Default;
 use std::env;
 use std::panic;
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index 8666ba357b8..144ff226c42 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -4,7 +4,7 @@ use crate::fold;
 use crate::fold::{DocFolder};
 use crate::passes::Pass;
 
-use std::mem::replace;
+use std::mem::take;
 
 pub const COLLAPSE_DOCS: Pass = Pass {
     name: "collapse-docs",
@@ -46,7 +46,7 @@ fn collapse(doc_strings: &mut Vec<DocFragment>) {
     let mut docs = vec![];
     let mut last_frag: Option<DocFragment> = None;
 
-    for frag in replace(doc_strings, vec![]) {
+    for frag in take(doc_strings) {
         if let Some(mut curr_frag) = last_frag.take() {
             let curr_kind = curr_frag.kind();
             let new_kind = frag.kind();
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index ddce5cab1eb..63545ab45bf 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -44,8 +44,7 @@ pub fn run(options: Options) -> i32 {
     let input = config::Input::File(options.input.clone());
 
     let sessopts = config::Options {
-        maybe_sysroot: options.maybe_sysroot.clone().or_else(
-            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
+        maybe_sysroot: options.maybe_sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types: vec![config::CrateType::Dylib],
         cg: options.codegen_options.clone(),
@@ -225,8 +224,7 @@ fn run_test(
     let outputs = OutputTypes::new(&[(OutputType::Exe, None)]);
 
     let sessopts = config::Options {
-        maybe_sysroot: maybe_sysroot.or_else(
-            || Some(env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_path_buf())),
+        maybe_sysroot,
         search_paths: libs,
         crate_types: vec![config::CrateType::Executable],
         output_types: outputs,
@@ -530,13 +528,8 @@ pub fn make_test(s: &str,
         prog.push_str(everything_else);
     } else {
         let returns_result = everything_else.trim_end().ends_with("(())");
-        let returns_option = everything_else.trim_end().ends_with("Some(())");
         let (main_pre, main_post) = if returns_result {
-            (if returns_option {
-                "fn main() { fn _inner() -> Option<()> {"
-            } else {
-                "fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {"
-            },
+            ("fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {",
              "}\n_inner().unwrap() }")
         } else {
             ("fn main() {\n", "\n}")
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 5a2fe2b244f..2925d8362c8 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -2608,6 +2608,12 @@ mod test_map {
     use realstd::collections::CollectionAllocErr::*;
     use realstd::usize;
 
+    // https://github.com/rust-lang/rust/issues/62301
+    fn _assert_hashmap_is_unwind_safe() {
+        fn assert_unwind_safe<T: crate::panic::UnwindSafe>() {}
+        assert_unwind_safe::<HashMap<(), crate::cell::UnsafeCell<()>>>();
+    }
+
     #[test]
     fn test_zero_capacities() {
         type HM = HashMap<i32, i32>;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 60e06139eba..fb9a228880e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -272,6 +272,7 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
+#![feature(mem_take)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 7a3b5d30500..1d4fd98dd75 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -4,6 +4,7 @@
 
 use crate::any::Any;
 use crate::cell::UnsafeCell;
+use crate::collections;
 use crate::fmt;
 use crate::future::Future;
 use crate::pin::Pin;
@@ -285,6 +286,11 @@ impl RefUnwindSafe for atomic::AtomicBool {}
 #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")]
 impl<T> RefUnwindSafe for atomic::AtomicPtr<T> {}
 
+// https://github.com/rust-lang/rust/issues/62301
+#[stable(feature = "hashbrown", since = "1.36.0")]
+impl<K, V, S> UnwindSafe for collections::HashMap<K, V, S>
+    where K: UnwindSafe, V: UnwindSafe, S: UnwindSafe {}
+
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T> Deref for AssertUnwindSafe<T> {
     type Target = T;
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 9ef42063f94..952fd9ebfdf 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -103,7 +103,9 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
         HOOK_LOCK.write_unlock();
 
         if let Hook::Custom(ptr) = old_hook {
-            Box::from_raw(ptr);
+            #[allow(unused_must_use)] {
+                Box::from_raw(ptr);
+            }
         }
     }
 }
@@ -362,7 +364,7 @@ fn continue_panic_fmt(info: &PanicInfo<'_>) -> ! {
 
     unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
         fn box_me_up(&mut self) -> *mut (dyn Any + Send) {
-            let contents = mem::replace(self.fill(), String::new());
+            let contents = mem::take(self.fill());
             Box::into_raw(Box::new(contents))
         }
 
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index a568f466637..000f80f99e7 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1765,33 +1765,6 @@ mod tests {
         assert_eq!(out, "foobar\n");
     }
 
-
-    #[test]
-    #[cfg_attr(target_os = "android", ignore)]
-    #[cfg(unix)]
-    fn uid_works() {
-        use crate::os::unix::prelude::*;
-
-        let mut p = Command::new("/bin/sh")
-                            .arg("-c").arg("true")
-                            .uid(unsafe { libc::getuid() })
-                            .gid(unsafe { libc::getgid() })
-                            .spawn().unwrap();
-        assert!(p.wait().unwrap().success());
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "android", ignore)]
-    #[cfg(unix)]
-    fn uid_to_root_fails() {
-        use crate::os::unix::prelude::*;
-
-        // if we're already root, this isn't a valid test. Most of the bots run
-        // as non-root though (android is an exception).
-        if unsafe { libc::getuid() == 0 } { return }
-        assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
-    }
-
     #[test]
     #[cfg_attr(target_os = "android", ignore)]
     fn test_process_status() {
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 3c4f8e077c9..f8fcd3ff5a5 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -383,7 +383,7 @@ impl<T> Packet<T> {
         // needs to be careful to destroy the data *outside* of the lock to
         // prevent deadlock.
         let _data = if guard.cap != 0 {
-            mem::replace(&mut guard.buf.buf, Vec::new())
+            mem::take(&mut guard.buf.buf)
         } else {
             Vec::new()
         };
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 47fb6792f08..4201de794b7 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -40,15 +40,15 @@ impl Condvar {
                   target_os = "android",
                   target_os = "hermit")))]
     pub unsafe fn init(&mut self) {
-        use crate::mem;
-        let mut attr: libc::pthread_condattr_t = mem::uninitialized();
-        let r = libc::pthread_condattr_init(&mut attr);
+        use crate::mem::MaybeUninit;
+        let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
+        let r = libc::pthread_condattr_init(attr.as_mut_ptr());
         assert_eq!(r, 0);
-        let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);
+        let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
         assert_eq!(r, 0);
-        let r = libc::pthread_cond_init(self.inner.get(), &attr);
+        let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr());
         assert_eq!(r, 0);
-        let r = libc::pthread_condattr_destroy(&mut attr);
+        let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
         assert_eq!(r, 0);
     }
 
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 3ccb0a1b1ab..41090caee84 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -40,10 +40,9 @@ use libc::MSG_NOSIGNAL;
               target_os = "haiku")))]
 const MSG_NOSIGNAL: libc::c_int = 0x0;
 
-fn sun_path_offset() -> usize {
+fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
     // Work with an actual instance of the type since using a null pointer is UB
-    let addr: libc::sockaddr_un = unsafe { mem::uninitialized() };
-    let base = &addr as *const _ as usize;
+    let base = addr as *const _ as usize;
     let path = &addr.sun_path as *const _ as usize;
     path - base
 }
@@ -69,7 +68,7 @@ unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::sockl
     // null byte for pathname addresses is already there because we zeroed the
     // struct
 
-    let mut len = sun_path_offset() + bytes.len();
+    let mut len = sun_path_offset(&addr) + bytes.len();
     match bytes.get(0) {
         Some(&0) | None => {}
         Some(_) => len += 1,
@@ -122,7 +121,7 @@ impl SocketAddr {
         if len == 0 {
             // When there is a datagram from unnamed unix socket
             // linux returns zero bytes of address
-            len = sun_path_offset() as libc::socklen_t;  // i.e., zero-length address
+            len = sun_path_offset(&addr) as libc::socklen_t;  // i.e., zero-length address
         } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
             return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                       "file descriptor did not correspond to a Unix socket"));
@@ -200,7 +199,7 @@ impl SocketAddr {
     }
 
     fn address<'a>(&'a self) -> AddressKind<'a> {
-        let len = self.len as usize - sun_path_offset();
+        let len = self.len as usize - sun_path_offset(&self.addr);
         let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
 
         // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
index b6a22e1962a..b43af8fdcaa 100644
--- a/src/libstd/sys/unix/mutex.rs
+++ b/src/libstd/sys/unix/mutex.rs
@@ -1,5 +1,5 @@
 use crate::cell::UnsafeCell;
-use crate::mem;
+use crate::mem::MaybeUninit;
 
 pub struct Mutex { inner: UnsafeCell<libc::pthread_mutex_t> }
 
@@ -40,14 +40,14 @@ impl Mutex {
         // references, we instead create the mutex with type
         // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
         // re-lock it from the same thread, thus avoiding undefined behavior.
-        let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
-        let r = libc::pthread_mutexattr_init(&mut attr);
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_settype(&mut attr, libc::PTHREAD_MUTEX_NORMAL);
+        let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutex_init(self.inner.get(), &attr);
+        let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
         debug_assert_eq!(r, 0);
-        let r = libc::pthread_mutexattr_destroy(&mut attr);
+        let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
         debug_assert_eq!(r, 0);
     }
     #[inline]
@@ -89,19 +89,19 @@ unsafe impl Sync for ReentrantMutex {}
 
 impl ReentrantMutex {
     pub unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: mem::uninitialized() }
+        ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
     }
 
     pub unsafe fn init(&mut self) {
-        let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
-        let result = libc::pthread_mutexattr_init(&mut attr as *mut _);
+        let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
+        let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutexattr_settype(&mut attr as *mut _,
+        let result = libc::pthread_mutexattr_settype(attr.as_mut_ptr(),
                                                     libc::PTHREAD_MUTEX_RECURSIVE);
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutex_init(self.inner.get(), &attr as *const _);
+        let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
         debug_assert_eq!(result, 0);
-        let result = libc::pthread_mutexattr_destroy(&mut attr as *mut _);
+        let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
         debug_assert_eq!(result, 0);
     }
 
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index f6a12a16396..3ff4f194cd1 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -437,7 +437,7 @@ mod tests {
 
     #[cfg(target_os = "android")]
     unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
-        libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>());
+        set.write_bytes(0u8, 1);
         return 0;
     }
 
@@ -466,11 +466,11 @@ mod tests {
             // Test to make sure that a signal mask does not get inherited.
             let mut cmd = Command::new(OsStr::new("cat"));
 
-            let mut set: libc::sigset_t = mem::uninitialized();
-            let mut old_set: libc::sigset_t = mem::uninitialized();
-            t!(cvt(sigemptyset(&mut set)));
-            t!(cvt(sigaddset(&mut set, libc::SIGINT)));
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
+            let mut set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+            let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+            t!(cvt(sigemptyset(set.as_mut_ptr())));
+            t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
+            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
 
             cmd.stdin(Stdio::MakePipe);
             cmd.stdout(Stdio::MakePipe);
@@ -479,7 +479,7 @@ mod tests {
             let stdin_write = pipes.stdin.take().unwrap();
             let stdout_read = pipes.stdout.take().unwrap();
 
-            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set,
+            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(),
                                          ptr::null_mut())));
 
             t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs
index 80fe763aecc..be38a1334ec 100644
--- a/src/libstd/sys/unix/process/process_unix.rs
+++ b/src/libstd/sys/unix/process/process_unix.rs
@@ -202,7 +202,7 @@ impl Command {
         // emscripten has no signal support.
         #[cfg(not(any(target_os = "emscripten")))]
         {
-            use crate::mem;
+            use crate::mem::MaybeUninit;
             // Reset signal handling so the child process starts in a
             // standardized state. libstd ignores SIGPIPE, and signal-handling
             // libraries often set a mask. Child processes inherit ignored
@@ -210,18 +210,16 @@ impl Command {
             // UNIX programs do not reset these things on their own, so we
             // need to clean things up now to avoid confusing the program
             // we're about to run.
-            let mut set: libc::sigset_t = mem::uninitialized();
+            let mut set = MaybeUninit::<libc::sigset_t>::uninit();
             if cfg!(target_os = "android") {
                 // Implementing sigemptyset allow us to support older Android
                 // versions. See the comment about Android and sig* functions in
                 // process_common.rs
-                libc::memset(&mut set as *mut _ as *mut _,
-                             0,
-                             mem::size_of::<libc::sigset_t>());
+                set.as_mut_ptr().write_bytes(0u8, 1);
             } else {
-                cvt(libc::sigemptyset(&mut set))?;
+                cvt(libc::sigemptyset(set.as_mut_ptr()))?;
             }
-            cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
+            cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(),
                                          ptr::null_mut()))?;
             let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
             if ret == libc::SIG_ERR {
@@ -273,7 +271,7 @@ impl Command {
     fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
         -> io::Result<Option<Process>>
     {
-        use crate::mem;
+        use crate::mem::MaybeUninit;
         use crate::sys;
 
         if self.get_gid().is_some() ||
@@ -315,63 +313,63 @@ impl Command {
 
         let mut p = Process { pid: 0, status: None };
 
-        struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
+        struct PosixSpawnFileActions(MaybeUninit<libc::posix_spawn_file_actions_t>);
 
         impl Drop for PosixSpawnFileActions {
             fn drop(&mut self) {
                 unsafe {
-                    libc::posix_spawn_file_actions_destroy(&mut self.0);
+                    libc::posix_spawn_file_actions_destroy(self.0.as_mut_ptr());
                 }
             }
         }
 
-        struct PosixSpawnattr(libc::posix_spawnattr_t);
+        struct PosixSpawnattr(MaybeUninit<libc::posix_spawnattr_t>);
 
         impl Drop for PosixSpawnattr {
             fn drop(&mut self) {
                 unsafe {
-                    libc::posix_spawnattr_destroy(&mut self.0);
+                    libc::posix_spawnattr_destroy(self.0.as_mut_ptr());
                 }
             }
         }
 
         unsafe {
-            let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
-            let mut attrs = PosixSpawnattr(mem::uninitialized());
+            let mut file_actions = PosixSpawnFileActions(MaybeUninit::uninit());
+            let mut attrs = PosixSpawnattr(MaybeUninit::uninit());
 
-            libc::posix_spawnattr_init(&mut attrs.0);
-            libc::posix_spawn_file_actions_init(&mut file_actions.0);
+            libc::posix_spawnattr_init(attrs.0.as_mut_ptr());
+            libc::posix_spawn_file_actions_init(file_actions.0.as_mut_ptr());
 
             if let Some(fd) = stdio.stdin.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDIN_FILENO))?;
             }
             if let Some(fd) = stdio.stdout.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDOUT_FILENO))?;
             }
             if let Some(fd) = stdio.stderr.fd() {
-                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
+                cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
                                                            fd,
                                                            libc::STDERR_FILENO))?;
             }
             if let Some((f, cwd)) = addchdir {
-                cvt(f(&mut file_actions.0, cwd.as_ptr()))?;
+                cvt(f(file_actions.0.as_mut_ptr(), cwd.as_ptr()))?;
             }
 
-            let mut set: libc::sigset_t = mem::uninitialized();
-            cvt(libc::sigemptyset(&mut set))?;
-            cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
-                                                 &set))?;
-            cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
-            cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
-                                                    &set))?;
+            let mut set = MaybeUninit::<libc::sigset_t>::uninit();
+            cvt(libc::sigemptyset(set.as_mut_ptr()))?;
+            cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(),
+                                                 set.as_ptr()))?;
+            cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
+            cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(),
+                                                    set.as_ptr()))?;
 
             let flags = libc::POSIX_SPAWN_SETSIGDEF |
                 libc::POSIX_SPAWN_SETSIGMASK;
-            cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;
+            cvt(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
 
             // Make sure we synchronize access to the global `environ` resource
             let _env_lock = sys::os::env_lock();
@@ -380,8 +378,8 @@ impl Command {
             let ret = libc::posix_spawnp(
                 &mut p.pid,
                 self.get_argv()[0],
-                &file_actions.0,
-                &attrs.0,
+                file_actions.0.as_ptr(),
+                attrs.0.as_ptr(),
                 self.get_argv().as_ptr() as *const _,
                 envp as *const _,
             );
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index 493ee8a9a2d..c77f30dfc71 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -342,7 +342,7 @@ impl<'a> Drop for AsyncPipe<'a> {
         // If anything here fails, there's not really much we can do, so we leak
         // the buffer/OVERLAPPED pointers to ensure we're at least memory safe.
         if self.pipe.cancel_io().is_err() || self.result().is_err() {
-            let buf = mem::replace(self.dst, Vec::new());
+            let buf = mem::take(self.dst);
             let overlapped = Box::new(unsafe { mem::zeroed() });
             let overlapped = mem::replace(&mut self.overlapped, overlapped);
             mem::forget((buf, overlapped));
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 436620ae729..453b6ebf3c4 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -440,12 +440,12 @@ pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
     })
 }
 
-pub fn find_by_name<'a>(attrs: &'a [Attribute], name: Symbol) -> Option<&'a Attribute> {
+pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
     attrs.iter().find(|attr| attr.check_name(name))
 }
 
-pub fn filter_by_name<'a>(attrs: &'a [Attribute], name: Symbol)
-    -> impl Iterator<Item = &'a Attribute> {
+pub fn filter_by_name(attrs: &[Attribute], name: Symbol)
+                      -> impl Iterator<Item=&Attribute> {
     attrs.iter().filter(move |attr| attr.check_name(name))
 }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 5473f55aa33..c71fa61443c 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -13,8 +13,7 @@ use crate::parse::{DirectoryOwnership, PResult, ParseSess};
 use crate::parse::token;
 use crate::parse::parser::Parser;
 use crate::ptr::P;
-use crate::symbol::Symbol;
-use crate::symbol::{kw, sym};
+use crate::symbol::{sym, Symbol};
 use crate::tokenstream::{TokenStream, TokenTree};
 use crate::visit::{self, Visitor};
 use crate::util::map_in_place::MapInPlace;
@@ -197,7 +196,6 @@ pub struct Invocation {
 pub enum InvocationKind {
     Bang {
         mac: ast::Mac,
-        ident: Option<Ident>,
         span: Span,
     },
     Attr {
@@ -307,7 +305,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             } else {
                 self.resolve_imports();
                 if undetermined_invocations.is_empty() { break }
-                invocations = mem::replace(&mut undetermined_invocations, Vec::new());
+                invocations = mem::take(&mut undetermined_invocations);
                 force = !mem::replace(&mut progress, false);
                 continue
             };
@@ -664,13 +662,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                          ext: &SyntaxExtension)
                          -> Option<AstFragment> {
         let kind = invoc.fragment_kind;
-        let (mac, ident, span) = match invoc.kind {
-            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
+        let (mac, span) = match invoc.kind {
+            InvocationKind::Bang { mac, span } => (mac, span),
             _ => unreachable!(),
         };
         let path = &mac.node.path;
 
-        let ident = ident.unwrap_or_else(|| Ident::invalid());
         let validate = |this: &mut Self| {
             // feature-gate the macro invocation
             if let Some((feature, issue)) = ext.unstable_feature {
@@ -690,12 +687,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
             }
 
-            if ident.name != kw::Invalid {
-                let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
-                this.cx.span_err(path.span, &msg);
-                this.cx.trace_macros_diag();
-                return Err(kind.dummy(span));
-            }
             Ok(())
         };
 
@@ -729,19 +720,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             }
 
             SyntaxExtensionKind::Bang(expander) => {
-                if ident.name != kw::Invalid {
-                    let msg =
-                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
-                    self.cx.span_err(path.span, &msg);
-                    self.cx.trace_macros_diag();
-                    kind.dummy(span)
-                } else {
-                    self.gate_proc_macro_expansion_kind(span, kind);
-                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
-                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
-                    self.gate_proc_macro_expansion(span, &result);
-                    result
-                }
+                self.gate_proc_macro_expansion_kind(span, kind);
+                let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                let result = self.parse_ast_fragment(tok_result, kind, path, span);
+                self.gate_proc_macro_expansion(span, &result);
+                result
             }
         };
 
@@ -944,7 +927,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
     }
 
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
-        self.collect(kind, InvocationKind::Bang { mac, ident: None, span })
+        self.collect(kind, InvocationKind::Bang { mac, span })
     }
 
     fn collect_attr(&mut self,
@@ -1179,13 +1162,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
             ast::ItemKind::Mac(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.node {
-                    ItemKind::Mac(mac) => {
-                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
-                            mac,
-                            ident: Some(item.ident),
-                            span: item.span,
-                        }).make_items()
-                    }
+                    ItemKind::Mac(mac) => self.collect(
+                        AstFragmentKind::Items, InvocationKind::Bang { mac, span: item.span }
+                    ).make_items(),
                     _ => unreachable!(),
                 })
             }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 92ce3779a3c..fc8aa4793bc 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -901,7 +901,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
 /// # Returns
 ///
 /// The parsed non-terminal.
-fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> Nonterminal {
+fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
     if name == sym::tt {
         return token::NtTT(p.parse_token_tree());
     }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index ea7f8e356aa..e04fd2ddc05 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -249,7 +249,7 @@ pub fn transcribe(
             quoted::TokenTree::Delimited(mut span, delimited) => {
                 span = span.apply_mark(cx.current_expansion.mark);
                 stack.push(Frame::Delimited { forest: delimited, idx: 0, span });
-                result_stack.push(mem::replace(&mut result, Vec::new()));
+                result_stack.push(mem::take(&mut result));
             }
 
             // Nothing much to do here. Just push the token to the result, being careful to
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index a6e8441a915..4a0c957333b 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -323,7 +323,7 @@ declare_features! (
     (active, nll, "1.0.0", Some(43234), None),
 
     // Allows using slice patterns.
-    (active, slice_patterns, "1.0.0", Some(23121), None),
+    (active, slice_patterns, "1.0.0", Some(62254), None),
 
     // Allows the definition of `const` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(57563), None),
@@ -530,9 +530,6 @@ declare_features! (
     // Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
     (active, lint_reasons, "1.31.0", Some(54503), None),
 
-    // Allows paths to enum variants on type aliases.
-    (active, type_alias_enum_variants, "1.31.0", Some(49683), None),
-
     // Allows exhaustive integer pattern matching on `usize` and `isize`.
     (active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
 
@@ -573,6 +570,9 @@ declare_features! (
     // Allows explicit discriminants on non-unit enum variants.
     (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
 
+    // Allows `impl Trait` with multiple unrelated lifetimes.
+    (active, member_constraints, "1.37.0", Some(61977), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -610,7 +610,7 @@ declare_features! (
     (removed, allocator, "1.0.0", None, None, None),
     (removed, simd, "1.0.0", Some(27731), None,
      Some("removed in favor of `#[repr(simd)]`")),
-    (removed, advanced_slice_patterns, "1.0.0", Some(23121), None,
+    (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
      Some("merged into `#![feature(slice_patterns)]`")),
     (removed, macro_reexport, "1.0.0", Some(29638), None,
      Some("subsumed by `pub use`")),
@@ -853,6 +853,8 @@ declare_features! (
     (accepted, extern_crate_self, "1.34.0", Some(56409), None),
     // Allows arbitrary delimited token streams in non-macro attributes.
     (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None),
+    // Allows paths to enum variants on type aliases including `Self`.
+    (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None),
     // Allows using `#[repr(align(X))]` on enums with equivalent semantics
     // to wrapping an enum in a wrapper struct with `#[repr(align(X))]`.
     (accepted, repr_align_enum, "1.37.0", Some(57996), None),
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 337b8424736..7f16bb9dc12 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -12,10 +12,12 @@
 #![deny(unused_lifetimes)]
 
 #![feature(bind_by_move_pattern_guards)]
+#![feature(box_syntax)]
 #![feature(const_fn)]
 #![feature(const_transmute)]
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
+#![feature(mem_take)]
 #![feature(nll)]
 #![feature(rustc_attrs)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 4e4fe4256c9..49f714e4e46 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -83,28 +83,6 @@ impl<'a> StringReader<'a> {
         Ok(ret_val)
     }
 
-    /// Immutably extract string if found at current position with given delimiters
-    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);
-        if ch != from_ch {
-            return None;
-        }
-        pos = pos + Pos::from_usize(ch.len_utf8());
-        let start_pos = pos;
-        idx = self.src_index(pos);
-        while idx < self.end_src_index {
-            ch = char_at(&self.src, idx);
-            if ch == to_ch {
-                return Some(self.src[self.src_index(start_pos)..self.src_index(pos)].to_string());
-            }
-            pos = pos + Pos::from_usize(ch.len_utf8());
-            idx = self.src_index(pos);
-        }
-        return None;
-    }
-
     fn try_real_token(&mut self) -> Result<Token, ()> {
         let mut t = self.try_next_token()?;
         loop {
diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs
index 94ce6297fbe..6a870685938 100644
--- a/src/libsyntax/parse/lexer/unicode_chars.rs
+++ b/src/libsyntax/parse/lexer/unicode_chars.rs
@@ -1,10 +1,11 @@
 // Characters and their corresponding confusables were collected from
 // http://www.unicode.org/Public/security/10.0.0/confusables.txt
 
-use syntax_pos::{Span, Pos, NO_EXPANSION};
-use errors::{Applicability, DiagnosticBuilder};
 use super::StringReader;
+use errors::{Applicability, DiagnosticBuilder};
+use syntax_pos::{Pos, Span, NO_EXPANSION};
 
+#[rustfmt::skip] // for line breaks
 const UNICODE_ARRAY: &[(char, &str, char)] = &[
     ('
', "Line Separator", ' '),
     ('
', "Paragraph Separator", ' '),
@@ -293,8 +294,8 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[
     ('〉', "Right-Pointing Angle Bracket", '>'),
     ('〉', "Right Angle Bracket", '>'),
     ('》', "Right Double Angle Bracket", '>'),
-    ('>', "Fullwidth Greater-Than Sign", '>'), ];
-
+    ('>', "Fullwidth Greater-Than Sign", '>'),
+];
 
 const ASCII_ARRAY: &[(char, &str)] = &[
     (' ', "Space"),
@@ -321,46 +322,72 @@ const ASCII_ARRAY: &[(char, &str)] = &[
     ('+', "Plus Sign"),
     ('<', "Less-Than Sign"),
     ('=', "Equals Sign"),
-    ('>', "Greater-Than Sign"), ];
-
-crate fn check_for_substitution<'a>(reader: &StringReader<'a>,
-                                  ch: char,
-                                  err: &mut DiagnosticBuilder<'a>) -> bool {
-    UNICODE_ARRAY
-    .iter()
-    .find(|&&(c, _, _)| c == ch)
-    .map(|&(_, u_name, ascii_char)| {
-        let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
-        match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
-            Some(&(ascii_char, ascii_name)) => {
-                // special help suggestion for "directed" double quotes
-                if let Some(s) = reader.peek_delimited('“', '”') {
-                    let msg = format!("Unicode characters '“' (Left Double Quotation Mark) and \
-                        '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
-                                ascii_char, ascii_name);
-                    err.span_suggestion(
-                        Span::new(reader.pos, reader.next_pos + Pos::from_usize(s.len()) +
-                            Pos::from_usize('”'.len_utf8()), NO_EXPANSION),
-                        &msg,
-                        format!("\"{}\"", s),
-                        Applicability::MaybeIncorrect);
-                } else {
-                    let msg =
-                        format!("Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
-                                ch, u_name, ascii_char, ascii_name);
-                    err.span_suggestion(
-                        span,
-                        &msg,
-                        ascii_char.to_string(),
-                        Applicability::MaybeIncorrect);
-                }
-                true
-            },
-            None => {
-                let msg = format!("substitution character not found for '{}'", ch);
-                reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
-                false
-            }
+    ('>', "Greater-Than Sign"),
+];
+
+crate fn check_for_substitution<'a>(
+    reader: &StringReader<'a>,
+    ch: char,
+    err: &mut DiagnosticBuilder<'a>,
+) -> bool {
+    let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) {
+        Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char),
+        None => return false,
+    };
+
+    let span = Span::new(reader.pos, reader.next_pos, NO_EXPANSION);
+
+    let ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
+        Some((_ascii_char, ascii_name)) => ascii_name,
+        None => {
+            let msg = format!("substitution character not found for '{}'", ch);
+            reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
+            return false
+        },
+    };
+
+    // special help suggestion for "directed" double quotes
+    if let Some(s) = reader.peek_delimited('“', '”') {
+        let msg = format!(
+            "Unicode characters '“' (Left Double Quotation Mark) and \
+             '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
+            ascii_char, ascii_name
+        );
+        err.span_suggestion(
+            Span::new(
+                reader.pos,
+                reader.next_pos + Pos::from_usize(s.len()) + Pos::from_usize('”'.len_utf8()),
+                NO_EXPANSION,
+            ),
+            &msg,
+            format!("\"{}\"", s),
+            Applicability::MaybeIncorrect,
+        );
+    } else {
+        let msg = format!(
+            "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
+            ch, u_name, ascii_char, ascii_name
+        );
+        err.span_suggestion(
+            span,
+            &msg,
+            ascii_char.to_string(),
+            Applicability::MaybeIncorrect,
+        );
+    }
+    true
+}
+
+impl StringReader<'_> {
+    /// Immutably extract string if found at current position with given delimiters
+    fn peek_delimited(&self, from_ch: char, to_ch: char) -> Option<&str> {
+        let tail = &self.src[self.src_index(self.pos)..];
+        let mut chars = tail.chars();
+        let first_char = chars.next()?;
+        if first_char != from_ch {
+            return None;
         }
-    }).unwrap_or(false)
+        let last_char_idx = chars.as_str().find(to_ch)?;
+        Some(&chars.as_str()[..last_char_idx])
+    }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index fc206580e38..9c179600093 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4324,51 +4324,49 @@ impl<'a> Parser<'a> {
     fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
                      -> PResult<'a, Option<P<Item>>> {
         let token_lo = self.token.span;
-        let (ident, def) = match self.token.kind {
-            token::Ident(name, false) if name == kw::Macro => {
-                self.bump();
-                let ident = self.parse_ident()?;
-                let tokens = if self.check(&token::OpenDelim(token::Brace)) {
-                    match self.parse_token_tree() {
-                        TokenTree::Delimited(_, _, tts) => tts,
-                        _ => unreachable!(),
-                    }
-                } else if self.check(&token::OpenDelim(token::Paren)) {
-                    let args = self.parse_token_tree();
-                    let body = if self.check(&token::OpenDelim(token::Brace)) {
-                        self.parse_token_tree()
-                    } else {
-                        self.unexpected()?;
-                        unreachable!()
-                    };
-                    TokenStream::new(vec![
-                        args.into(),
-                        TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(),
-                        body.into(),
-                    ])
+        let (ident, def) = if self.eat_keyword(kw::Macro) {
+            let ident = self.parse_ident()?;
+            let tokens = if self.check(&token::OpenDelim(token::Brace)) {
+                match self.parse_token_tree() {
+                    TokenTree::Delimited(_, _, tts) => tts,
+                    _ => unreachable!(),
+                }
+            } else if self.check(&token::OpenDelim(token::Paren)) {
+                let args = self.parse_token_tree();
+                let body = if self.check(&token::OpenDelim(token::Brace)) {
+                    self.parse_token_tree()
                 } else {
                     self.unexpected()?;
                     unreachable!()
                 };
+                TokenStream::new(vec![
+                    args.into(),
+                    TokenTree::token(token::FatArrow, token_lo.to(self.prev_span)).into(),
+                    body.into(),
+                ])
+            } else {
+                self.unexpected()?;
+                unreachable!()
+            };
 
-                (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
-            }
-            token::Ident(name, _) if name == sym::macro_rules &&
-                                     self.look_ahead(1, |t| *t == token::Not) => {
-                let prev_span = self.prev_span;
-                self.complain_if_pub_macro(&vis.node, prev_span);
-                self.bump();
-                self.bump();
-
-                let ident = self.parse_ident()?;
-                let (delim, tokens) = self.expect_delimited_token_tree()?;
-                if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
-                    self.report_invalid_macro_expansion_item();
-                }
+            (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
+        } else if self.check_keyword(sym::macro_rules) &&
+                  self.look_ahead(1, |t| *t == token::Not) &&
+                  self.look_ahead(2, |t| t.is_ident()) {
+            let prev_span = self.prev_span;
+            self.complain_if_pub_macro(&vis.node, prev_span);
+            self.bump();
+            self.bump();
 
-                (ident, ast::MacroDef { tokens, legacy: true })
+            let ident = self.parse_ident()?;
+            let (delim, tokens) = self.expect_delimited_token_tree()?;
+            if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
+                self.report_invalid_macro_expansion_item();
             }
-            _ => return Ok(None),
+
+            (ident, ast::MacroDef { tokens, legacy: true })
+        } else {
+            return Ok(None);
         };
 
         let span = lo.to(self.prev_span);
@@ -4412,14 +4410,14 @@ impl<'a> Parser<'a> {
                   !self.is_existential_type_decl() &&
                   !self.is_auto_trait_item() &&
                   !self.is_async_fn() {
-            let pth = self.parse_path(PathStyle::Expr)?;
+            let path = self.parse_path(PathStyle::Expr)?;
 
             if !self.eat(&token::Not) {
                 let expr = if self.check(&token::OpenDelim(token::Brace)) {
-                    self.parse_struct_expr(lo, pth, ThinVec::new())?
+                    self.parse_struct_expr(lo, path, ThinVec::new())?
                 } else {
                     let hi = self.prev_span;
-                    self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new())
+                    self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new())
                 };
 
                 let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
@@ -4434,34 +4432,6 @@ impl<'a> Parser<'a> {
                 }));
             }
 
-            // it's a macro invocation
-            let id = match self.token.kind {
-                token::OpenDelim(_) => Ident::invalid(), // no special identifier
-                _ => self.parse_ident()?,
-            };
-
-            // check that we're pointing at delimiters (need to check
-            // again after the `if`, because of `parse_ident`
-            // consuming more tokens).
-            match self.token.kind {
-                token::OpenDelim(_) => {}
-                _ => {
-                    // we only expect an ident if we didn't parse one
-                    // above.
-                    let ident_str = if id.name == kw::Invalid {
-                        "identifier, "
-                    } else {
-                        ""
-                    };
-                    let tok_str = self.this_token_descr();
-                    let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
-                                                      ident_str,
-                                                      tok_str));
-                    err.span_label(self.token.span, format!("expected {}`(` or `{{`", ident_str));
-                    return Err(err)
-                },
-            }
-
             let (delim, tts) = self.expect_delimited_token_tree()?;
             let hi = self.prev_span;
 
@@ -4471,59 +4441,38 @@ impl<'a> Parser<'a> {
                 MacStmtStyle::NoBraces
             };
 
-            if id.name == kw::Invalid {
-                let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
-                let node = if delim == MacDelimiter::Brace ||
-                              self.token == token::Semi || self.token == token::Eof {
-                    StmtKind::Mac(P((mac, style, attrs.into())))
-                }
-                // We used to incorrectly stop parsing macro-expanded statements here.
-                // If the next token will be an error anyway but could have parsed with the
-                // earlier behavior, stop parsing here and emit a warning to avoid breakage.
-                else if macro_legacy_warnings &&
-                        self.token.can_begin_expr() &&
-                        match self.token.kind {
-                    // These can continue an expression, so we can't stop parsing and warn.
-                    token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
-                    token::BinOp(token::Minus) | token::BinOp(token::Star) |
-                    token::BinOp(token::And) | token::BinOp(token::Or) |
-                    token::AndAnd | token::OrOr |
-                    token::DotDot | token::DotDotDot | token::DotDotEq => false,
-                    _ => true,
-                } {
-                    self.warn_missing_semicolon();
-                    StmtKind::Mac(P((mac, style, attrs.into())))
-                } else {
-                    let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
-                    let e = self.maybe_recover_from_bad_qpath(e, true)?;
-                    let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
-                    let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
-                    StmtKind::Expr(e)
-                };
-                Stmt {
-                    id: ast::DUMMY_NODE_ID,
-                    span: lo.to(hi),
-                    node,
-                }
+            let mac = respan(lo.to(hi), Mac_ { path, tts, delim });
+            let node = if delim == MacDelimiter::Brace ||
+                          self.token == token::Semi || self.token == token::Eof {
+                StmtKind::Mac(P((mac, style, attrs.into())))
+            }
+            // We used to incorrectly stop parsing macro-expanded statements here.
+            // If the next token will be an error anyway but could have parsed with the
+            // earlier behavior, stop parsing here and emit a warning to avoid breakage.
+            else if macro_legacy_warnings &&
+                    self.token.can_begin_expr() &&
+                    match self.token.kind {
+                // These can continue an expression, so we can't stop parsing and warn.
+                token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
+                token::BinOp(token::Minus) | token::BinOp(token::Star) |
+                token::BinOp(token::And) | token::BinOp(token::Or) |
+                token::AndAnd | token::OrOr |
+                token::DotDot | token::DotDotDot | token::DotDotEq => false,
+                _ => true,
+            } {
+                self.warn_missing_semicolon();
+                StmtKind::Mac(P((mac, style, attrs.into())))
             } else {
-                // if it has a special ident, it's definitely an item
-                //
-                // Require a semicolon or braces.
-                if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
-                    self.report_invalid_macro_expansion_item();
-                }
-                let span = lo.to(hi);
-                Stmt {
-                    id: ast::DUMMY_NODE_ID,
-                    span,
-                    node: StmtKind::Item({
-                        self.mk_item(
-                            span, id /*id is good here*/,
-                            ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
-                            respan(lo, VisibilityKind::Inherited),
-                            attrs)
-                    }),
-                }
+                let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
+                let e = self.maybe_recover_from_bad_qpath(e, true)?;
+                let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+                let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+                StmtKind::Expr(e)
+            };
+            Stmt {
+                id: ast::DUMMY_NODE_ID,
+                span: lo.to(hi),
+                node,
             }
         } else {
             // FIXME: Bad copy of attrs
@@ -5734,9 +5683,12 @@ impl<'a> Parser<'a> {
     {
         let is_const_fn = self.eat_keyword(kw::Const);
         let const_span = self.prev_span;
-        let unsafety = self.parse_unsafety();
         let asyncness = self.parse_asyncness();
+        if let IsAsync::Async { .. } = asyncness {
+            self.ban_async_in_2015(self.prev_span);
+        }
         let asyncness = respan(self.prev_span, asyncness);
+        let unsafety = self.parse_unsafety();
         let (constness, unsafety, abi) = if is_const_fn {
             (respan(const_span, Constness::Const), unsafety, Abi::Rust)
         } else {
@@ -7254,13 +7206,7 @@ impl<'a> Parser<'a> {
                                         item_,
                                         visibility,
                                         maybe_append(attrs, extra_attrs));
-                if self.token.span.rust_2015() {
-                    self.diagnostic().struct_span_err_with_code(
-                        async_span,
-                        "`async fn` is not permitted in the 2015 edition",
-                        DiagnosticId::Error("E0670".into())
-                    ).emit();
-                }
+                self.ban_async_in_2015(async_span);
                 return Ok(Some(item));
             }
         }
@@ -7534,6 +7480,19 @@ impl<'a> Parser<'a> {
         self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility)
     }
 
+    /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
+    fn ban_async_in_2015(&self, async_span: Span) {
+        if async_span.rust_2015() {
+            self.diagnostic()
+                .struct_span_err_with_code(
+                    async_span,
+                    "`async fn` is not permitted in the 2015 edition",
+                    DiagnosticId::Error("E0670".into())
+                )
+                .emit();
+        }
+    }
+
     /// Parses a foreign item.
     crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
         maybe_whole!(self, NtForeignItem, |ni| ni);
@@ -7609,26 +7568,17 @@ impl<'a> Parser<'a> {
             let mac_lo = self.token.span;
 
             // item macro.
-            let pth = self.parse_path(PathStyle::Mod)?;
+            let path = self.parse_path(PathStyle::Mod)?;
             self.expect(&token::Not)?;
-
-            // a 'special' identifier (like what `macro_rules!` uses)
-            // is optional. We should eventually unify invoc syntax
-            // and remove this.
-            let id = if self.token.is_ident() {
-                self.parse_ident()?
-            } else {
-                Ident::invalid() // no special identifier
-            };
-            // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
             if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
                 self.report_invalid_macro_expansion_item();
             }
 
             let hi = self.prev_span;
-            let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
-            let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
+            let mac = respan(mac_lo.to(hi), Mac_ { path, tts, delim });
+            let item =
+                self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
             return Ok(Some(item));
         }
 
@@ -7654,9 +7604,9 @@ impl<'a> Parser<'a> {
                 !(self.is_async_fn() && self.token.span.rust_2015()) {
             let prev_span = self.prev_span;
             let lo = self.token.span;
-            let pth = self.parse_path(PathStyle::Mod)?;
+            let path = self.parse_path(PathStyle::Mod)?;
 
-            if pth.segments.len() == 1 {
+            if path.segments.len() == 1 {
                 if !self.eat(&token::Not) {
                     return Err(self.missing_assoc_item_kind_err(item_kind, prev_span));
                 }
@@ -7676,7 +7626,7 @@ impl<'a> Parser<'a> {
                 self.expect(&token::Semi)?;
             }
 
-            Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))
+            Ok(Some(respan(lo.to(self.prev_span), Mac_ { path, tts, delim })))
         } else {
             Ok(None)
         }
@@ -7689,7 +7639,7 @@ impl<'a> Parser<'a> {
         let mut tokens = Vec::new();
         let prev_collecting = match self.token_cursor.frame.last_token {
             LastToken::Collecting(ref mut list) => {
-                Some(mem::replace(list, Vec::new()))
+                Some(mem::take(list))
             }
             LastToken::Was(ref mut last) => {
                 tokens.extend(last.take());
@@ -7707,7 +7657,7 @@ impl<'a> Parser<'a> {
 
         // Pull out the tokens that we've collected from the call to `f` above.
         let mut collected_tokens = match *last_token {
-            LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
+            LastToken::Collecting(ref mut v) => mem::take(v),
             LastToken::Was(_) => panic!("our vector went away?"),
         };
 
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index f0cfa5a84a8..be580dc2e6a 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -41,11 +41,11 @@ pub struct P<T: ?Sized> {
     ptr: Box<T>
 }
 
-#[allow(non_snake_case)]
 /// Construct a `P<T>` from a `T` value.
+#[allow(non_snake_case)]
 pub fn P<T: 'static>(value: T) -> P<T> {
     P {
-        ptr: Box::new(value)
+        ptr: box value
     }
 }
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index f90b76721ee..156fab8834c 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -120,8 +120,8 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
         if let ast::ItemKind::Mod(mut module) = item.node {
-            let tests = mem::replace(&mut self.tests, Vec::new());
-            let tested_submods = mem::replace(&mut self.tested_submods, Vec::new());
+            let tests = mem::take(&mut self.tests);
+            let tested_submods = mem::take(&mut self.tested_submods);
             noop_visit_mod(&mut module, self);
             let tests = mem::replace(&mut self.tests, tests);
             let tested_submods = mem::replace(&mut self.tested_submods, tested_submods);
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index 733c4f83e37..f850960624c 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -20,7 +20,7 @@ pub fn string_to_stream(source_str: String) -> TokenStream {
 }
 
 /// Map string to parser (via tts)
-pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
+pub fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
     new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
 }
 
diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs
index 10d323ffb89..637614a18bc 100644
--- a/src/libsyntax_ext/assert.rs
+++ b/src/libsyntax_ext/assert.rs
@@ -131,7 +131,7 @@ fn parse_assert<'a>(
     Ok(Assert { cond_expr, custom_message })
 }
 
-fn parse_custom_message<'a>(parser: &mut Parser<'a>) -> Option<TokenStream> {
+fn parse_custom_message(parser: &mut Parser<'_>) -> Option<TokenStream> {
     let ts = parser.parse_tokens();
     if !ts.is_empty() {
         Some(ts)
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 444cf1263ce..12482f7248e 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -331,8 +331,8 @@ pub type CombineSubstructureFunc<'a> =
 pub type EnumNonMatchCollapsedFunc<'a> =
     Box<dyn FnMut(&mut ExtCtxt<'_>, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
 
-pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
-                                -> RefCell<CombineSubstructureFunc<'a>> {
+pub fn combine_substructure(f: CombineSubstructureFunc<'_>)
+                            -> RefCell<CombineSubstructureFunc<'_>> {
     RefCell::new(f)
 }
 
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index 90d826429da..02b02e9b836 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -39,10 +39,10 @@ pub enum PathKind {
 }
 
 impl<'a> Path<'a> {
-    pub fn new<'r>(path: Vec<&'r str>) -> Path<'r> {
+    pub fn new(path: Vec<&str>) -> Path<'_> {
         Path::new_(path, None, Vec::new(), PathKind::Std)
     }
-    pub fn new_local<'r>(path: &'r str) -> Path<'r> {
+    pub fn new_local(path: &str) -> Path<'_> {
         Path::new_(vec![path], None, Vec::new(), PathKind::Local)
     }
     pub fn new_<'r>(path: Vec<&'r str>,
@@ -117,7 +117,7 @@ pub enum Const {
 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
     Borrowed(None, ast::Mutability::Immutable)
 }
-pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
+pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
     Ptr(ty, borrowed_ptrty())
 }
 
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index bd9a9061b99..aee988d5148 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -389,6 +389,7 @@ symbols! {
         match_beginning_vert,
         match_default_bindings,
         may_dangle,
+        member_constraints,
         message,
         meta,
         min_const_fn,
@@ -1132,6 +1133,7 @@ impl LocalInternedString {
         }
     }
 
+    #[inline]
     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.
@@ -1145,6 +1147,7 @@ impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString
 where
     str: std::convert::AsRef<U>
 {
+    #[inline]
     fn as_ref(&self) -> &U {
         self.string.as_ref()
     }
@@ -1185,6 +1188,7 @@ impl !Sync for LocalInternedString {}
 
 impl std::ops::Deref for LocalInternedString {
     type Target = str;
+    #[inline]
     fn deref(&self) -> &str { self.string }
 }
 
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index 20280aa3c41..e92c68f5b0c 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -4,11 +4,13 @@ fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
-    if cfg!(feature = "llvm-libunwind") &&
+    // FIXME: the not(bootstrap) part is needed because of the issue addressed by #62286,
+    // and could be removed once that change is in beta.
+    if cfg!(all(not(bootstrap), feature = "llvm-libunwind")) &&
         (target.contains("linux") ||
          target.contains("fuchsia")) {
         // Build the unwinding from libunwind C/C++ source code.
-        #[cfg(feature = "llvm-libunwind")]
+        #[cfg(all(not(bootstrap), feature = "llvm-libunwind"))]
         llvm_libunwind::compile();
     } else if target.contains("linux") {
         if target.contains("musl") {
@@ -42,7 +44,7 @@ fn main() {
     }
 }
 
-#[cfg(feature = "llvm-libunwind")]
+#[cfg(all(not(bootstrap), feature = "llvm-libunwind"))]
 mod llvm_libunwind {
     use std::env;
     use std::path::Path;
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index 5794e0b7683..7e640897af7 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -67,6 +67,8 @@ pub enum _Unwind_Context {}
 
 pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
                                                       exception: *mut _Unwind_Exception);
+#[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind"),
+           link(name = "unwind", kind = "static"))]
 extern "C" {
     #[unwind(allowed)]
     pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
@@ -91,6 +93,8 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
     }
     pub use _Unwind_Action::*;
 
+    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind"),
+               link(name = "unwind", kind = "static"))]
     extern "C" {
         pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
         pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
@@ -144,6 +148,8 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
     pub const UNWIND_POINTER_REG: c_int = 12;
     pub const UNWIND_IP_REG: c_int = 15;
 
+    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind"),
+               link(name = "unwind", kind = "static"))]
     extern "C" {
         fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                            regclass: _Unwind_VRS_RegClass,
@@ -206,6 +212,8 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
 cfg_if::cfg_if! {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
+    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind"),
+               link(name = "unwind", kind = "static"))]
     extern "C" {
         #[unwind(allowed)]
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
@@ -215,6 +223,8 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     }
 } else {
     // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+    #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind"),
+               link(name = "unwind", kind = "static"))]
     extern "C" {
         #[unwind(allowed)]
         pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
diff --git a/src/test/codegen/pgo-instrumentation.rs b/src/test/codegen/pgo-instrumentation.rs
index e9436505886..8200cf4e016 100644
--- a/src/test/codegen/pgo-instrumentation.rs
+++ b/src/test/codegen/pgo-instrumentation.rs
@@ -1,8 +1,8 @@
-// Test that `-Zpgo-gen` creates expected instrumentation artifacts in LLVM IR.
+// Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR.
 // Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms.
 
 // needs-profiler-support
-// compile-flags: -Z pgo-gen -Ccodegen-units=1 -Cpanic=abort
+// compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort
 
 // CHECK: @__llvm_profile_raw_version =
 // CHECK: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = private global
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 13daa72a4d1..34f30548c5a 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
@@ -5,7 +5,7 @@
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
index 9e34aedbed3..662aa535331 100644
--- a/src/test/incremental/change_add_field/struct_point.rs
+++ b/src/test/incremental/change_add_field/struct_point.rs
@@ -5,7 +5,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/test/incremental/change_crate_dep_kind.rs b/src/test/incremental/change_crate_dep_kind.rs
index 04a41d71cc9..f5d1acb621b 100644
--- a/src/test/incremental/change_crate_dep_kind.rs
+++ b/src/test/incremental/change_crate_dep_kind.rs
@@ -3,7 +3,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph -Cpanic=unwind
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(panic_unwind)]
 
diff --git a/src/test/incremental/change_private_fn/struct_point.rs b/src/test/incremental/change_private_fn/struct_point.rs
index be287b86bbc..722e62ef11d 100644
--- a/src/test/incremental/change_private_fn/struct_point.rs
+++ b/src/test/incremental/change_private_fn/struct_point.rs
@@ -3,7 +3,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
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 521fe99ebc2..384441d6d0c 100644
--- a/src/test/incremental/change_private_fn_cc/struct_point.rs
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -4,7 +4,7 @@
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
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 c2796b5e3c9..ec5899f3119 100644
--- a/src/test/incremental/change_private_impl_method/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method/struct_point.rs
@@ -3,7 +3,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
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 731dcdf78c9..f0e78f8d0a4 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
@@ -4,7 +4,7 @@
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
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 76dcff848ca..641d20ed6cc 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
@@ -2,7 +2,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
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 9c95d4cc2a9..9b8f9517bf1 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
@@ -2,7 +2,7 @@
 
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index 55dd3745123..d859cbef39f 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index 5165f9821fd..24ab6b8e184 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
index 516276a49ea..8e713a1d992 100644
--- a/src/test/incremental/hashes/consts.rs
+++ b/src/test/incremental/hashes/consts.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index f553b2d1b51..575b2e92966 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index aa2dc798b81..7256c1aa153 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -10,7 +10,7 @@
 // results in a change of the ICH for the enum's metadata, and that it stays
 // the same between rev2 and rev3.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
index 5a29afa17d3..ef275cabeaf 100644
--- a/src/test/incremental/hashes/exported_vs_not.rs
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index e6423ebad12..0b9a0fd7945 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index 503cb8732ef..ca45d36a6b0 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 7850291fc56..84680a52ff3 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index 6bc7d286e3a..b84c393573b 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index eb0c33f7766..4d39ed68701 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 268c37508a7..882383e8419 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index 53e77a370a3..deb1c45a528 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index e016b92a9eb..68545b7daaa 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index c04bdd43a95..6222d948c98 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
index 02f2cd6634d..840b2222d90 100644
--- a/src/test/incremental/hashes/match_expressions.rs
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
index 0803f4e01d6..b370fcce8ef 100644
--- a/src/test/incremental/hashes/panic_exprs.rs
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -8,7 +8,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -C debug-assertions
 
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
index 3bee2aca5b6..6f74e0fdbc0 100644
--- a/src/test/incremental/hashes/statics.rs
+++ b/src/test/incremental/hashes/statics.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index e478ff96c32..b708b99eabc 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index 8d32e33054c..e0c56964831 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -10,7 +10,7 @@
 // results in a change of the ICH for the struct's metadata, and that it stays
 // the same between rev2 and rev3.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index da57b485beb..30b4e306820 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -10,7 +10,7 @@
 // results in a change of the ICH for the trait's metadata, and that it stays
 // the same between rev2 and rev3.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
index 1487129d09e..fa28b2ebedd 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs
index 4ffa0d9bb7b..264e8f926ff 100644
--- a/src/test/incremental/hashes/type_defs.rs
+++ b/src/test/incremental/hashes/type_defs.rs
@@ -10,7 +10,7 @@
 // results in a change of the ICH for the enum's metadata, and that it stays
 // the same between rev2 and rev3.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index 8c53ae6a038..776a0273ca7 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index 2d48707561c..af2066b90f1 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index 79a3bc9b205..d8ec76d76aa 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -5,7 +5,7 @@
 // and make sure that the hash has changed, then change nothing between rev2 and
 // rev3 and make sure that the hash has not changed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index 3c2ce765c48..b2b7e663151 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -2,7 +2,7 @@
 // the nested items (or even added new ones).
 
 // revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/incremental_proc_macro.rs b/src/test/incremental/incremental_proc_macro.rs
index b0e9b1f9180..becc1538fb2 100644
--- a/src/test/incremental/incremental_proc_macro.rs
+++ b/src/test/incremental/incremental_proc_macro.rs
@@ -1,6 +1,6 @@
 // aux-build:incremental_proc_macro_aux.rs
 // revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test makes sure that we still find the proc-macro registrar function
 // when we compile proc-macros incrementally (see #47292).
diff --git a/src/test/incremental/issue-42602.rs b/src/test/incremental/issue-42602.rs
index 17e1b821878..b8d5303fb47 100644
--- a/src/test/incremental/issue-42602.rs
+++ b/src/test/incremental/issue-42602.rs
@@ -8,7 +8,7 @@
 
 // revisions:cfail1 cfail2 cfail3
 // compile-flags:-Zquery-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/issue-49595/issue-49595.rs b/src/test/incremental/issue-49595/issue-49595.rs
index ada93f79b26..ab4d76eef36 100644
--- a/src/test/incremental/issue-49595/issue-49595.rs
+++ b/src/test/incremental/issue-49595/issue-49595.rs
@@ -1,6 +1,6 @@
 // revisions:cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph --test
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
diff --git a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
index afc08621340..709e9be663e 100644
--- a/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
+++ b/src/test/incremental/issue-59523-on-implemented-is-not-unused.rs
@@ -3,7 +3,7 @@
 // subsequent runs) if incremental compilation is enabled.
 
 // revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(on_unimplemented)]
 #![deny(unused_attributes)]
diff --git a/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs
index 37bd8d0641f..bfb5e539cc1 100644
--- a/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs
+++ b/src/test/incremental/issue-59524-layout-scalar-valid-range-is-not-unused.rs
@@ -4,7 +4,7 @@
 // enabled.
 
 // revisions: cfail1 cfail2
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![deny(unused_attributes)]
diff --git a/src/test/incremental/krate-inherent.rs b/src/test/incremental/krate-inherent.rs
index 3e8d8fb1f94..6e791eacdf3 100644
--- a/src/test/incremental/krate-inherent.rs
+++ b/src/test/incremental/krate-inherent.rs
@@ -1,6 +1,6 @@
 // revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/macro_export.rs b/src/test/incremental/macro_export.rs
index d1966646867..044d63fd2a9 100644
--- a/src/test/incremental/macro_export.rs
+++ b/src/test/incremental/macro_export.rs
@@ -1,5 +1,5 @@
 // revisions: cfail1 cfail2 cfail3
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test case makes sure that we can compile with incremental compilation
 // enabled when there are macros exported from this crate. (See #37756)
diff --git a/src/test/incremental/remove_source_file/main.rs b/src/test/incremental/remove_source_file/main.rs
index 3af9c051892..b2411c0946f 100644
--- a/src/test/incremental/remove_source_file/main.rs
+++ b/src/test/incremental/remove_source_file/main.rs
@@ -6,7 +6,7 @@
 // Note that we specify -g so that the SourceFiles actually get referenced by the
 // incr. comp. cache:
 // compile-flags: -Z query-dep-graph -g
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type= "rlib"]
 
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index c39d4145b58..b88acd2af75 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -1,6 +1,6 @@
 // revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/thinlto/cgu_invalidated_via_import.rs b/src/test/incremental/thinlto/cgu_invalidated_via_import.rs
index 09c429f0ad8..8160f8f3a99 100644
--- a/src/test/incremental/thinlto/cgu_invalidated_via_import.rs
+++ b/src/test/incremental/thinlto/cgu_invalidated_via_import.rs
@@ -4,7 +4,7 @@
 
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -O
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
diff --git a/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs b/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs
index da6aa79b9d3..24e5d2438bd 100644
--- a/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs
+++ b/src/test/incremental/thinlto/independent_cgus_dont_affect_each_other.rs
@@ -3,7 +3,7 @@
 
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Z query-dep-graph -O
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs
index f2acaa0121b..a1d11f8aa5b 100644
--- a/src/test/incremental/warnings-reemitted.rs
+++ b/src/test/incremental/warnings-reemitted.rs
@@ -1,6 +1,6 @@
 // revisions: cfail1 cfail2 cfail3
 // compile-flags: -Coverflow-checks=on
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 #![warn(const_err)]
diff --git a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile
index 59a7d61892f..f8efeca5614 100644
--- a/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile
+++ b/src/test/run-make-fulldeps/cross-lang-lto-pgo-smoketest/Makefile
@@ -21,7 +21,7 @@ all: cpp-executable rust-executable
 
 cpp-executable:
 	$(RUSTC) -Clinker-plugin-lto=on \
-	         -Zpgo-gen="$(TMPDIR)"/cpp-profdata \
+	         -Cprofile-generate="$(TMPDIR)"/cpp-profdata \
 	         -o "$(TMPDIR)"/librustlib-xlto.a \
 	         $(COMMON_FLAGS) \
 	         ./rustlib.rs
@@ -39,7 +39,7 @@ cpp-executable:
 		-o "$(TMPDIR)"/cpp-profdata/merged.profdata \
 		"$(TMPDIR)"/cpp-profdata/default_*.profraw
 	$(RUSTC) -Clinker-plugin-lto=on \
-	         -Zpgo-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
+	         -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
 	         -o "$(TMPDIR)"/librustlib-xlto.a \
 	         $(COMMON_FLAGS) \
 	         ./rustlib.rs
@@ -57,7 +57,7 @@ rust-executable:
 	$(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3
 	(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
 	$(RUSTC) -Clinker-plugin-lto=on \
-	         -Zpgo-gen="$(TMPDIR)"/rs-profdata \
+	         -Cprofile-generate="$(TMPDIR)"/rs-profdata \
 	         -L$(TMPDIR) \
 	         $(COMMON_FLAGS) \
 	         -Clinker=$(CLANG) \
@@ -78,7 +78,7 @@ rust-executable:
 	rm "$(TMPDIR)"/libxyz.a
 	(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
 	$(RUSTC) -Clinker-plugin-lto=on \
-	         -Zpgo-use="$(TMPDIR)"/rs-profdata/merged.profdata \
+	         -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
 	         -L$(TMPDIR) \
 	         $(COMMON_FLAGS) \
 	         -Clinker=$(CLANG) \
diff --git a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
index 56f31434ade..6c70d951c35 100644
--- a/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen-lto/Makefile
@@ -2,7 +2,7 @@
 
 -include ../tools.mk
 
-COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
 
 # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
 # https://github.com/rust-lang/rust/issues/61002
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
index bb86160d2df..3fbfeb09eb3 100644
--- a/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen-no-imp-symbols/Makefile
@@ -2,7 +2,7 @@
 
 -include ../tools.mk
 
-COMPILE_FLAGS=-O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)"
 
 # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
 # https://github.com/rust-lang/rust/issues/61002
diff --git a/src/test/run-make-fulldeps/pgo-gen/Makefile b/src/test/run-make-fulldeps/pgo-gen/Makefile
index f0ab3b7d13d..3b66427c14c 100644
--- a/src/test/run-make-fulldeps/pgo-gen/Makefile
+++ b/src/test/run-make-fulldeps/pgo-gen/Makefile
@@ -2,7 +2,7 @@
 
 -include ../tools.mk
 
-COMPILE_FLAGS=-g -Z pgo-gen="$(TMPDIR)"
+COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)"
 
 # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC:
 # https://github.com/rust-lang/rust/issues/61002
diff --git a/src/test/run-make-fulldeps/pgo-use/Makefile b/src/test/run-make-fulldeps/pgo-use/Makefile
index 72c3c34ee37..61a73587759 100644
--- a/src/test/run-make-fulldeps/pgo-use/Makefile
+++ b/src/test/run-make-fulldeps/pgo-use/Makefile
@@ -33,7 +33,7 @@ endif
 
 all:
 	# Compile the test program with instrumentation
-	$(RUSTC) $(COMMON_FLAGS) -Z pgo-gen="$(TMPDIR)" main.rs
+	$(RUSTC) $(COMMON_FLAGS) -Cprofile-generate="$(TMPDIR)" main.rs
 	# Run it in order to generate some profiling data
 	$(call RUN,main some-argument) || exit 1
 	# Postprocess the profiling data so it can be used by the compiler
@@ -41,7 +41,7 @@ all:
 		-o "$(TMPDIR)"/merged.profdata \
 		"$(TMPDIR)"/default_*.profraw
 	# Compile the test program again, making use of the profiling data
-	$(RUSTC) $(COMMON_FLAGS) -Z pgo-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
+	$(RUSTC) $(COMMON_FLAGS) -Cprofile-use="$(TMPDIR)"/merged.profdata --emit=llvm-ir main.rs
 	# Check that the generate IR contains some things that we expect
 	#
 	# We feed the file into LLVM FileCheck tool *in reverse* so that we see the
diff --git a/src/test/run-pass/async-await/async-fn-size-moved-locals.rs b/src/test/run-pass/async-await/async-fn-size-moved-locals.rs
new file mode 100644
index 00000000000..139be7fe013
--- /dev/null
+++ b/src/test/run-pass/async-await/async-fn-size-moved-locals.rs
@@ -0,0 +1,98 @@
+// Test that we don't duplicate storage for futures moved around in .await, and
+// for futures moved into other futures.
+//
+// The exact sizes can change by a few bytes (we'd like to know when they do).
+// What we don't want to see is the wrong multiple of 1024 (the size of BigFut)
+// being reflected in the size.
+//
+// See issue #59123 for a full explanation.
+
+// edition:2018
+
+#![feature(async_await)]
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+const BIG_FUT_SIZE: usize = 1024;
+struct BigFut([u8; BIG_FUT_SIZE]);
+
+impl BigFut {
+    fn new() -> Self {
+        BigFut([0; BIG_FUT_SIZE])
+    } }
+
+impl Drop for BigFut {
+    fn drop(&mut self) {}
+}
+
+impl Future for BigFut {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(())
+    }
+}
+
+#[allow(dead_code)]
+struct Joiner {
+    a: Option<BigFut>,
+    b: Option<BigFut>,
+    c: Option<BigFut>,
+}
+
+impl Future for Joiner {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(())
+    }
+}
+
+fn noop() {}
+
+async fn single() {
+    let x = BigFut::new();
+    x.await;
+}
+
+async fn single_with_noop() {
+    let x = BigFut::new();
+    noop();
+    x.await;
+}
+
+async fn joined() {
+    let a = BigFut::new();
+    let b = BigFut::new();
+    let c = BigFut::new();
+
+    let joiner = Joiner {
+        a: Some(a),
+        b: Some(b),
+        c: Some(c),
+    };
+    joiner.await
+}
+
+async fn joined_with_noop() {
+    let a = BigFut::new();
+    let b = BigFut::new();
+    let c = BigFut::new();
+
+    let joiner = Joiner {
+        a: Some(a),
+        b: Some(b),
+        c: Some(c),
+    };
+    noop();
+    joiner.await
+}
+
+fn main() {
+    assert_eq!(1028, std::mem::size_of_val(&single()));
+    assert_eq!(1032, std::mem::size_of_val(&single_with_noop()));
+    assert_eq!(3084, std::mem::size_of_val(&joined()));
+    assert_eq!(3084, std::mem::size_of_val(&joined_with_noop()));
+}
diff --git a/src/test/run-pass/async-fn-size.rs b/src/test/run-pass/async-await/async-fn-size.rs
index 05afd6d4019..c4e328560dd 100644
--- a/src/test/run-pass/async-fn-size.rs
+++ b/src/test/run-pass/async-await/async-fn-size.rs
@@ -1,9 +1,9 @@
 // edition:2018
-// aux-build:arc_wake.rs
 
 #![feature(async_await, await_macro)]
 
-extern crate arc_wake;
+#[path = "../auxiliary/arc_wake.rs"]
+mod arc_wake;
 
 use std::pin::Pin;
 use std::future::Future;
diff --git a/src/test/run-pass/async-await/issue-60709.rs b/src/test/run-pass/async-await/issue-60709.rs
new file mode 100644
index 00000000000..778d3ee0c70
--- /dev/null
+++ b/src/test/run-pass/async-await/issue-60709.rs
@@ -0,0 +1,28 @@
+// This used to compile the future down to ud2, due to uninhabited types being
+// handled incorrectly in generators.
+// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
+
+#![feature(async_await, await_macro)]
+#![allow(unused)]
+
+use std::future::Future;
+use std::task::Poll;
+use std::task::Context;
+use std::pin::Pin;
+use std::rc::Rc;
+
+struct Never();
+impl Future for Never {
+    type Output = ();
+    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+        Poll::Pending
+    }
+}
+
+fn main() {
+    let fut = async {
+        let _rc = Rc::new(()); // Also crashes with Arc
+        await!(Never());
+    };
+    let _bla = fut; // Moving the future is required.
+}
diff --git a/src/test/run-pass/command-uid-gid.rs b/src/test/run-pass/command-uid-gid.rs
new file mode 100644
index 00000000000..2b52c5d104c
--- /dev/null
+++ b/src/test/run-pass/command-uid-gid.rs
@@ -0,0 +1,26 @@
+#![feature(rustc_private)]
+
+fn main() {
+    #[cfg(unix)]
+    run()
+}
+
+#[cfg(unix)]
+fn run() {
+    extern crate libc;
+    use std::process::Command;
+    use std::os::unix::prelude::*;
+
+    let mut p = Command::new("/bin/sh")
+        .arg("-c").arg("true")
+        .uid(unsafe { libc::getuid() })
+        .gid(unsafe { libc::getgid() })
+        .spawn().unwrap();
+    assert!(p.wait().unwrap().success());
+
+    // if we're already root, this isn't a valid test. Most of the bots run
+    // as non-root though (android is an exception).
+    if unsafe { libc::getuid() != 0 } {
+        assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
+    }
+}
diff --git a/src/test/run-pass/generator/size-moved-locals.rs b/src/test/run-pass/generator/size-moved-locals.rs
new file mode 100644
index 00000000000..37e2e0cfdcc
--- /dev/null
+++ b/src/test/run-pass/generator/size-moved-locals.rs
@@ -0,0 +1,62 @@
+// Test that we don't duplicate storage for a variable that is moved to another
+// binding. This used to happen in the presence of unwind and drop edges (see
+// `complex` below.)
+//
+// The exact sizes here can change (we'd like to know when they do). What we
+// don't want to see is the `complex` generator size being upwards of 2048 bytes
+// (which would indicate it is reserving space for two copies of Foo.)
+//
+// See issue #59123 for a full explanation.
+
+// edition:2018
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+const FOO_SIZE: usize = 1024;
+struct Foo([u8; FOO_SIZE]);
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+fn move_before_yield() -> impl Generator<Yield = (), Return = ()> {
+    static || {
+        let first = Foo([0; FOO_SIZE]);
+        let _second = first;
+        yield;
+        // _second dropped here
+    }
+}
+
+fn noop() {}
+
+fn move_before_yield_with_noop() -> impl Generator<Yield = (), Return = ()> {
+    static || {
+        let first = Foo([0; FOO_SIZE]);
+        noop();
+        let _second = first;
+        yield;
+        // _second dropped here
+    }
+}
+
+// Today we don't have NRVO (we allocate space for both `first` and `second`,)
+// but we can overlap `first` with `_third`.
+fn overlap_move_points() -> impl Generator<Yield = (), Return = ()> {
+    static || {
+        let first = Foo([0; FOO_SIZE]);
+        yield;
+        let second = first;
+        yield;
+        let _third = second;
+        yield;
+    }
+}
+
+fn main() {
+    assert_eq!(1028, std::mem::size_of_val(&move_before_yield()));
+    assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop()));
+    assert_eq!(2056, std::mem::size_of_val(&overlap_move_points()));
+}
diff --git a/src/test/run-pass/issues/issue-30530.rs b/src/test/run-pass/issues/issue-30530.rs
index e837fc81721..111fb8aa506 100644
--- a/src/test/run-pass/issues/issue-30530.rs
+++ b/src/test/run-pass/issues/issue-30530.rs
@@ -12,7 +12,9 @@ pub enum Handler {
 }
 
 fn main() {
-    take(Handler::Default, Box::new(main));
+    #[allow(unused_must_use)] {
+        take(Handler::Default, Box::new(main));
+    }
 }
 
 #[inline(never)]
diff --git a/src/test/run-pass/packed/packed-with-inference-vars-issue-61402.rs b/src/test/run-pass/packed/packed-with-inference-vars-issue-61402.rs
new file mode 100644
index 00000000000..6028b8f5ab4
--- /dev/null
+++ b/src/test/run-pass/packed/packed-with-inference-vars-issue-61402.rs
@@ -0,0 +1,21 @@
+// If a struct is packed and its last field has drop glue, then that
+// field needs to be Sized (to allow it to be destroyed out-of-place).
+//
+// This is checked by the compiler during wfcheck. That check used
+// to have problems with associated types in the last field - test
+// that this doesn't ICE.
+
+#![allow(unused_imports, dead_code)]
+
+pub struct S;
+
+pub trait Trait<R> { type Assoc; }
+
+impl<X> Trait<X> for S { type Assoc = X; }
+
+#[repr(C, packed)]
+struct PackedAssocSized {
+    pos: Box<<S as Trait<usize>>::Assoc>,
+}
+
+fn main() { println!("Hello, world!"); }
diff --git a/src/test/run-pass/panics/panic-handler-flail-wildly.rs b/src/test/run-pass/panics/panic-handler-flail-wildly.rs
index ebe4f70378c..6badd203842 100644
--- a/src/test/run-pass/panics/panic-handler-flail-wildly.rs
+++ b/src/test/run-pass/panics/panic-handler-flail-wildly.rs
@@ -1,5 +1,7 @@
 // run-pass
+
 #![allow(stable_features)]
+#![allow(unused_must_use)]
 
 // ignore-emscripten no threads support
 
diff --git a/src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs b/src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs
index 51a3b46d461..0ab7e17f87b 100644
--- a/src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs
+++ b/src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![feature(decl_macro)]
 
-r#macro_rules! r#struct {
+macro_rules! r#struct {
     ($r#struct:expr) => { $r#struct }
 }
 
diff --git a/src/test/run-pass/type-alias-enum-variants-2.rs b/src/test/run-pass/type-alias-enum-variants-2.rs
deleted file mode 100644
index 0cf413babcb..00000000000
--- a/src/test/run-pass/type-alias-enum-variants-2.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-#[derive(Debug, PartialEq, Eq)]
-enum Foo {
-    Bar(i32),
-    Baz { i: i32 },
-}
-
-type FooAlias = Foo;
-type OptionAlias = Option<i32>;
-
-impl Foo {
-    fn foo() -> Self {
-        Self::Bar(3)
-    }
-}
-
-fn main() {
-    let t = FooAlias::Bar(1);
-    assert_eq!(t, Foo::Bar(1));
-    let t = FooAlias::Baz { i: 2 };
-    assert_eq!(t, Foo::Baz { i: 2 });
-    match t {
-        FooAlias::Bar(_i) => {}
-        FooAlias::Baz { i } => { assert_eq!(i, 2); }
-    }
-    assert_eq!(Foo::foo(), Foo::Bar(3));
-
-    assert_eq!(OptionAlias::Some(4), Option::Some(4));
-}
diff --git a/src/test/run-pass/type-alias-enum-variants.rs b/src/test/run-pass/type-alias-enum-variants.rs
deleted file mode 100644
index 0cf413babcb..00000000000
--- a/src/test/run-pass/type-alias-enum-variants.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-#[derive(Debug, PartialEq, Eq)]
-enum Foo {
-    Bar(i32),
-    Baz { i: i32 },
-}
-
-type FooAlias = Foo;
-type OptionAlias = Option<i32>;
-
-impl Foo {
-    fn foo() -> Self {
-        Self::Bar(3)
-    }
-}
-
-fn main() {
-    let t = FooAlias::Bar(1);
-    assert_eq!(t, Foo::Bar(1));
-    let t = FooAlias::Baz { i: 2 };
-    assert_eq!(t, Foo::Baz { i: 2 });
-    match t {
-        FooAlias::Bar(_i) => {}
-        FooAlias::Baz { i } => { assert_eq!(i, 2); }
-    }
-    assert_eq!(Foo::foo(), Foo::Bar(3));
-
-    assert_eq!(OptionAlias::Some(4), Option::Some(4));
-}
diff --git a/src/test/rustdoc-ui/cfg-test.rs b/src/test/rustdoc-ui/cfg-test.rs
index e26034371f4..4dcf512d286 100644
--- a/src/test/rustdoc-ui/cfg-test.rs
+++ b/src/test/rustdoc-ui/cfg-test.rs
@@ -1,13 +1,16 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:--test
 // normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
 
+// Crates like core have doctests gated on `cfg(not(test))` so we need to make
+// sure `cfg(test)` is not active when running `rustdoc --test`.
+
 /// this doctest will be ignored:
 ///
 /// ```
 /// assert!(false);
 /// ```
-#[cfg(not(test))]
+#[cfg(test)]
 pub struct Foo;
 
 /// this doctest will be tested:
@@ -15,5 +18,5 @@ pub struct Foo;
 /// ```
 /// assert!(true);
 /// ```
-#[cfg(test)]
+#[cfg(not(test))]
 pub struct Foo;
diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout
index 30bb0038d1b..67873870e89 100644
--- a/src/test/rustdoc-ui/cfg-test.stdout
+++ b/src/test/rustdoc-ui/cfg-test.stdout
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/cfg-test.rs - Foo (line 15) ... ok
+test $DIR/cfg-test.rs - Foo (line 18) ... ok
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
 
diff --git a/src/test/rustdoc-ui/coverage/basic.rs b/src/test/rustdoc-ui/coverage/basic.rs
index 4247fdf9895..d25ac633d7b 100644
--- a/src/test/rustdoc-ui/coverage/basic.rs
+++ b/src/test/rustdoc-ui/coverage/basic.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(extern_types)]
 
diff --git a/src/test/rustdoc-ui/coverage/empty.rs b/src/test/rustdoc-ui/coverage/empty.rs
index 463617a1143..27bcf6f3938 100644
--- a/src/test/rustdoc-ui/coverage/empty.rs
+++ b/src/test/rustdoc-ui/coverage/empty.rs
@@ -1,4 +1,4 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // an empty crate still has one item to document: the crate root
diff --git a/src/test/rustdoc-ui/coverage/enums.rs b/src/test/rustdoc-ui/coverage/enums.rs
index 5cd7f490d1a..e4171d7cfb2 100644
--- a/src/test/rustdoc-ui/coverage/enums.rs
+++ b/src/test/rustdoc-ui/coverage/enums.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 //! (remember the crate root is still a module)
 
diff --git a/src/test/rustdoc-ui/coverage/exotic.rs b/src/test/rustdoc-ui/coverage/exotic.rs
index b4adf45b90b..414d6f84058 100644
--- a/src/test/rustdoc-ui/coverage/exotic.rs
+++ b/src/test/rustdoc-ui/coverage/exotic.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(doc_keyword)]
 
diff --git a/src/test/rustdoc-ui/coverage/private.rs b/src/test/rustdoc-ui/coverage/private.rs
index 9024185856d..6ff1bfa7275 100644
--- a/src/test/rustdoc-ui/coverage/private.rs
+++ b/src/test/rustdoc-ui/coverage/private.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage --document-private-items
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(unused)]
 
diff --git a/src/test/rustdoc-ui/coverage/statics-consts.rs b/src/test/rustdoc-ui/coverage/statics-consts.rs
index 3c1dd35dfe1..b7d2b1dc10c 100644
--- a/src/test/rustdoc-ui/coverage/statics-consts.rs
+++ b/src/test/rustdoc-ui/coverage/statics-consts.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 //! gotta make sure we can count statics and consts correctly, too
 
diff --git a/src/test/rustdoc-ui/coverage/traits.rs b/src/test/rustdoc-ui/coverage/traits.rs
index 5f32d5b0ccc..40d68423f1b 100644
--- a/src/test/rustdoc-ui/coverage/traits.rs
+++ b/src/test/rustdoc-ui/coverage/traits.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Z unstable-options --show-coverage
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(trait_alias)]
 
diff --git a/src/test/rustdoc-ui/deprecated-attrs.rs b/src/test/rustdoc-ui/deprecated-attrs.rs
index 6f6d5b8b654..21169eeb8c8 100644
--- a/src/test/rustdoc-ui/deprecated-attrs.rs
+++ b/src/test/rustdoc-ui/deprecated-attrs.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![doc(no_default_passes, passes = "collapse-docs unindent-comments")]
 
diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.rs b/src/test/rustdoc-ui/intra-links-warning-crlf.rs
index 20f761fcf4f..67bd9f73eeb 100644
--- a/src/test/rustdoc-ui/intra-links-warning-crlf.rs
+++ b/src/test/rustdoc-ui/intra-links-warning-crlf.rs
@@ -1,6 +1,6 @@
 // ignore-tidy-cr
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This file checks the spans of intra-link warnings in a file with CRLF line endings. The
 // .gitattributes file in this directory should enforce it.
diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs
index 26d4598f7ad..20770efa953 100644
--- a/src/test/rustdoc-ui/intra-links-warning.rs
+++ b/src/test/rustdoc-ui/intra-links-warning.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
        //! Test with [Foo::baz], [Bar::foo], ...
      //! , [Uniooon::X] and [Qux::Z].
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index 924e0386d31..2b02d47d4b8 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 /// ```
 /// \__________pkt->size___________/          \_result->size_/ \__pkt->size__/
diff --git a/src/test/rustdoc-ui/issue-58473-2.rs b/src/test/rustdoc-ui/issue-58473-2.rs
index 5e5ddebe108..1bb19353ba2 100644
--- a/src/test/rustdoc-ui/issue-58473-2.rs
+++ b/src/test/rustdoc-ui/issue-58473-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(private_doc_tests)]
 
diff --git a/src/test/rustdoc-ui/issue-58473.rs b/src/test/rustdoc-ui/issue-58473.rs
index 0e5be3292c0..6756d3b5a60 100644
--- a/src/test/rustdoc-ui/issue-58473.rs
+++ b/src/test/rustdoc-ui/issue-58473.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub trait Foo {
     /**
diff --git a/src/test/rustdoc-ui/unused.rs b/src/test/rustdoc-ui/unused.rs
index e82a41b7a7b..ffa421d4f7f 100644
--- a/src/test/rustdoc-ui/unused.rs
+++ b/src/test/rustdoc-ui/unused.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test purpose is to check that unused_imports lint isn't fired
 // by rustdoc. Why would it? Because when rustdoc is running, it uses
diff --git a/src/test/rustdoc/process-termination.rs b/src/test/rustdoc/process-termination.rs
index 31ae0143d47..32258792b6e 100644
--- a/src/test/rustdoc/process-termination.rs
+++ b/src/test/rustdoc/process-termination.rs
@@ -21,16 +21,4 @@
 /// Err("This is returned from `main`, leading to panic")?;
 /// Ok::<(), &'static str>(())
 /// ```
-///
-/// This also works with `Option<()>`s now:
-///
-/// ```rust
-/// Some(())
-/// ```
-///
-/// ```rust,should_panic
-/// let x: &[u32] = &[];
-/// let _ = x.iter().next()?;
-/// Some(())
-/// ```
 pub fn check_process_termination() {}
diff --git a/src/test/ui/anon-params-deprecated.fixed b/src/test/ui/anon-params-deprecated.fixed
index 7eee47dcb5f..fe42113eb2e 100644
--- a/src/test/ui/anon-params-deprecated.fixed
+++ b/src/test/ui/anon-params-deprecated.fixed
@@ -1,7 +1,7 @@
 #![warn(anonymous_parameters)]
 // Test for the anonymous_parameters deprecation lint (RFC 1685)
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2015
 // run-rustfix
 
diff --git a/src/test/ui/anon-params-deprecated.rs b/src/test/ui/anon-params-deprecated.rs
index 74de0c0b834..dc0357721ec 100644
--- a/src/test/ui/anon-params-deprecated.rs
+++ b/src/test/ui/anon-params-deprecated.rs
@@ -1,7 +1,7 @@
 #![warn(anonymous_parameters)]
 // Test for the anonymous_parameters deprecation lint (RFC 1685)
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2015
 // run-rustfix
 
diff --git a/src/test/ui/associated-const/associated-const-trait-bound.rs b/src/test/ui/associated-const/associated-const-trait-bound.rs
index 0ce46d312af..403cdbd7ff3 100644
--- a/src/test/ui/associated-const/associated-const-trait-bound.rs
+++ b/src/test/ui/associated-const/associated-const-trait-bound.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait ConstDefault {
     const DEFAULT: Self;
diff --git a/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs b/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs
index 1b3e978594d..f5a9bac6e35 100644
--- a/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs
+++ b/src/test/ui/associated-type-bounds/entails-sized-object-safety.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/associated-type-bounds/trait-params.rs b/src/test/ui/associated-type-bounds/trait-params.rs
index a9081d50cfc..b0703a4ee22 100644
--- a/src/test/ui/associated-type-bounds/trait-params.rs
+++ b/src/test/ui/associated-type-bounds/trait-params.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/associated-type-bounds/type-alias.rs b/src/test/ui/associated-type-bounds/type-alias.rs
index 1602fdd275a..34bc0c9acbf 100644
--- a/src/test/ui/associated-type-bounds/type-alias.rs
+++ b/src/test/ui/associated-type-bounds/type-alias.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs
index 38261ca4570..0eae1467fbf 100644
--- a/src/test/ui/async-await/async-await.rs
+++ b/src/test/ui/async-await/async-await.rs
@@ -134,11 +134,15 @@ trait Bar {
 }
 
 impl Foo {
-    async fn async_method(x: u8) -> u8 {
+    async fn async_assoc_item(x: u8) -> u8 {
         unsafe {
             unsafe_async_fn(x).await
         }
     }
+
+    async unsafe fn async_unsafe_assoc_item(x: u8) -> u8 {
+        unsafe_async_fn(x).await
+    }
 }
 
 fn test_future_yields_once_then_returns<F, Fut>(f: F)
@@ -180,12 +184,17 @@ fn main() {
         async_fn,
         generic_async_fn,
         async_fn_with_internal_borrow,
-        Foo::async_method,
+        Foo::async_assoc_item,
         |x| {
             async move {
                 unsafe { unsafe_async_fn(x).await }
             }
         },
+        |x| {
+            async move {
+                unsafe { Foo::async_unsafe_assoc_item(x).await }
+            }
+        },
     }
     test_with_borrow! {
         async_block_with_borrow_named_lifetime,
diff --git a/src/test/ui/async-await/async-fn-multiple-lifetimes.rs b/src/test/ui/async-await/async-fn-multiple-lifetimes.rs
deleted file mode 100644
index e3ac817b15c..00000000000
--- a/src/test/ui/async-await/async-fn-multiple-lifetimes.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// edition:2018
-
-#![feature(arbitrary_self_types, async_await, await_macro, pin)]
-
-use std::ops::Add;
-
-async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
-//~^ ERROR ambiguous lifetime bound in `async fn`
-
-async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
-    _: impl for<'a> Add<&'a u8>,
-    _: impl for<'b> Add<&'b u8>,
-    _: &'c u8,
-) {}
-
-async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-//~^ ambiguous lifetime bound in `async fn`
-
-fn main() {}
diff --git a/src/test/ui/async-await/async-fn-multiple-lifetimes.stderr b/src/test/ui/async-await/async-fn-multiple-lifetimes.stderr
deleted file mode 100644
index 8c3ee2bed83..00000000000
--- a/src/test/ui/async-await/async-fn-multiple-lifetimes.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-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) {}
-   |                                                                 ^ neither `'a` nor `'b` outlives the other
-   |
-   = 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: ambiguous lifetime bound in `async fn`
-  --> $DIR/async-fn-multiple-lifetimes.rs:16:52
-   |
-LL | async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
-   |                                                    ^ the elided lifetimes here do not outlive one another
-   |
-   = 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: aborting due to 2 previous errors
-
diff --git a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs
index f07fc2fceb5..5e1b8c6280b 100644
--- a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs
+++ b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // compile-flags: --crate-type lib
 
diff --git a/src/test/ui/async-await/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs
index f375d58d984..e41a568ad29 100644
--- a/src/test/ui/async-await/async-matches-expr.rs
+++ b/src/test/ui/async-await/async-matches-expr.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/async-with-closure.rs b/src/test/ui/async-await/async-with-closure.rs
index e94a5f0853d..2b69c9b701a 100644
--- a/src/test/ui/async-await/async-with-closure.rs
+++ b/src/test/ui/async-await/async-with-closure.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
index e1111f9e0e4..a5bc1810154 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
@@ -28,6 +28,12 @@ fn main() {
         async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
     }
 
+    accept_item! {
+        impl Foo {
+            async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+        }
+    }
+
     let inside_closure = || {
         async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
     };
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index 05a06124dc2..efb4462095d 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -23,7 +23,19 @@ LL | async fn async_baz() {
    | ^^^^^
 
 error[E0670]: `async fn` is not permitted in the 2015 edition
-  --> $DIR/edition-deny-async-fns-2015.rs:32:9
+  --> $DIR/edition-deny-async-fns-2015.rs:16:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:38:9
    |
 LL |         async fn bar() {}
    |         ^^^^^
@@ -35,10 +47,10 @@ LL |         async fn foo() {}
    |         ^^^^^
 
 error[E0670]: `async fn` is not permitted in the 2015 edition
-  --> $DIR/edition-deny-async-fns-2015.rs:16:5
+  --> $DIR/edition-deny-async-fns-2015.rs:33:13
    |
-LL |     async fn foo() {}
-   |     ^^^^^
+LL |             async fn bar() {}
+   |             ^^^^^
 
 error[E0706]: trait fns cannot be declared `async`
   --> $DIR/edition-deny-async-fns-2015.rs:20:5
@@ -46,12 +58,6 @@ error[E0706]: trait fns cannot be declared `async`
 LL |     async fn foo() {}
    |     ^^^^^^^^^^^^^^^^^
 
-error[E0670]: `async fn` is not permitted in the 2015 edition
-  --> $DIR/edition-deny-async-fns-2015.rs:20:5
-   |
-LL |     async fn foo() {}
-   |     ^^^^^
-
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0670`.
diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs
index 913f1435c6a..8b60f2f82f1 100644
--- a/src/test/ui/async-await/generics-and-bounds.rs
+++ b/src/test/ui/async-await/generics-and-bounds.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // compile-flags: --crate-type lib
 
diff --git a/src/test/ui/async-await/issue-61793.rs b/src/test/ui/async-await/issue-61793.rs
index bccdf0113ff..a18fad8bb91 100644
--- a/src/test/ui/async-await/issue-61793.rs
+++ b/src/test/ui/async-await/issue-61793.rs
@@ -3,7 +3,7 @@
 // while those two fields were at the same offset (which is impossible).
 // That is, memory ordering of `(X, ())`, but offsets of `((), X)`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await)]
diff --git a/src/test/ui/async-await/issues/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs
index 2157cf7d4f7..c493878e4c2 100644
--- a/src/test/ui/async-await/issues/issue-53249.rs
+++ b/src/test/ui/async-await/issues/issue-53249.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(arbitrary_self_types, async_await, await_macro)]
diff --git a/src/test/ui/async-await/issues/issue-54974.rs b/src/test/ui/async-await/issues/issue-54974.rs
index ad18f411875..0cfe859b13b 100644
--- a/src/test/ui/async-await/issues/issue-54974.rs
+++ b/src/test/ui/async-await/issues/issue-54974.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/issues/issue-55324.rs b/src/test/ui/async-await/issues/issue-55324.rs
index 4572e543f22..deaba6904f4 100644
--- a/src/test/ui/async-await/issues/issue-55324.rs
+++ b/src/test/ui/async-await/issues/issue-55324.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/issues/issue-58885.rs b/src/test/ui/async-await/issues/issue-58885.rs
index 99d87b2273c..5868e022861 100644
--- a/src/test/ui/async-await/issues/issue-58885.rs
+++ b/src/test/ui/async-await/issues/issue-58885.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/issues/issue-59001.rs b/src/test/ui/async-await/issues/issue-59001.rs
index c758244002f..ffa70d3b43c 100644
--- a/src/test/ui/async-await/issues/issue-59001.rs
+++ b/src/test/ui/async-await/issues/issue-59001.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, await_macro)]
diff --git a/src/test/ui/async-await/issues/issue-60518.rs b/src/test/ui/async-await/issues/issue-60518.rs
index f603c5bd3f9..e4bdc96511e 100644
--- a/src/test/ui/async-await/issues/issue-60518.rs
+++ b/src/test/ui/async-await/issues/issue-60518.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await)]
diff --git a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs
index a4fe8650129..2328ceb144f 100644
--- a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs
+++ b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs
@@ -1,6 +1,6 @@
 // Test that existential types are allowed to contain late-bound regions.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(async_await, existential_type)]
diff --git a/src/test/ui/async-await/issues/issue-60674.rs b/src/test/ui/async-await/issues/issue-60674.rs
index ecb80803383..99cdcbafc76 100644
--- a/src/test/ui/async-await/issues/issue-60674.rs
+++ b/src/test/ui/async-await/issues/issue-60674.rs
@@ -1,5 +1,5 @@
 // aux-build:issue-60674.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 #![feature(async_await)]
 
diff --git a/src/test/ui/async-await/issues/issue-61986.rs b/src/test/ui/async-await/issues/issue-61986.rs
index da8b22bc104..77ecc47dfef 100644
--- a/src/test/ui/async-await/issues/issue-61986.rs
+++ b/src/test/ui/async-await/issues/issue-61986.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 //
 // Tests that we properly handle StorageDead/StorageLives for temporaries
diff --git a/src/test/ui/async-await/multiple-lifetimes/elided.rs b/src/test/ui/async-await/multiple-lifetimes/elided.rs
new file mode 100644
index 00000000000..45f3170d4c3
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/elided.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(async_await)]
+
+async fn multiple_elided_lifetimes(_: &u8, _: &u8) {}
+
+fn main() {
+    let _ = multiple_elided_lifetimes(&22, &44);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs
new file mode 100644
index 00000000000..a7254cee755
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(async_await)]
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {}
+
+fn gimme(_: &u8) { }
+
+fn main() {
+    let _ = multiple_named_lifetimes(&22, &44, gimme);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs
new file mode 100644
index 00000000000..620b0080966
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs
@@ -0,0 +1,17 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(arbitrary_self_types, async_await, await_macro)]
+#![allow(dead_code)]
+
+use std::ops::Add;
+
+async fn multiple_hrtb_and_single_named_lifetime_ok<'c>(
+    _: impl for<'a> Add<&'a u8>,
+    _: impl for<'b> Add<&'b u8>,
+    _: &'c u8,
+) {}
+
+fn main() {}
diff --git a/src/test/ui/async-await/multiple-lifetimes/named.rs b/src/test/ui/async-await/multiple-lifetimes/named.rs
new file mode 100644
index 00000000000..7d13d48bc8b
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/named.rs
@@ -0,0 +1,12 @@
+// edition:2018
+// run-pass
+
+// Test that we can use async fns with multiple arbitrary lifetimes.
+
+#![feature(arbitrary_self_types, async_await, await_macro)]
+
+async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {}
+
+fn main() {
+    let _ = multiple_named_lifetimes(&22, &44);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs
new file mode 100644
index 00000000000..903c43950a5
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs
@@ -0,0 +1,15 @@
+// edition:2018
+// run-pass
+
+#![feature(async_await)]
+
+async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32)
+    where 'b: 'a
+{
+    drop((a, c));
+    (b, b)
+}
+
+fn main() {
+    let _ = lotsa_lifetimes(&22, &44, &66);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs
new file mode 100644
index 00000000000..08622311f7b
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs
@@ -0,0 +1,18 @@
+// edition:2018
+// run-pass
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await, member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+    (a, b)
+}
+
+fn main() {
+    let _ = async_ret_impl_trait(&22, &44);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
new file mode 100644
index 00000000000..08ecea4cc85
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs
@@ -0,0 +1,18 @@
+// edition:2018
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+    //~^ ERROR ambiguous lifetime bound
+    (a, b)
+}
+
+fn main() {
+    let _ = async_ret_impl_trait(&22, &44);
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
new file mode 100644
index 00000000000..de2c85d772a
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr
@@ -0,0 +1,10 @@
+error: ambiguous lifetime bound in `impl Trait`
+  --> $DIR/ret-impl-trait-no-fg.rs:11:64
+   |
+LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+   |                                                                ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+   |
+   = help: add #![feature(member_constraints)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
new file mode 100644
index 00000000000..b4d5d3ec051
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.nll.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/ret-impl-trait-one.rs:12:80
+   |
+LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |  ________________________________--__--__________________________________________^
+   | |                                |   |
+   | |                                |   lifetime `'b` defined here
+   | |                                lifetime `'a` defined here
+LL | |
+LL | |     (a, b)
+LL | | }
+   | |_^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs
new file mode 100644
index 00000000000..e1b71465273
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs
@@ -0,0 +1,27 @@
+// edition:2018
+
+// Test that a feature gate is needed to use `impl Trait` as the
+// return type of an async.
+
+#![feature(async_await, member_constraints)]
+
+trait Trait<'a> { }
+impl<T> Trait<'_> for T { }
+
+// Only `'a` permitted in return type, not `'b`.
+async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+    //~^ ERROR lifetime mismatch
+    (a, b)
+}
+
+// As above, but `'b: 'a`, so return type can be inferred to `(&'a u8,
+// &'a u8)`.
+async fn async_ret_impl_trait2<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a>
+where
+    'b: 'a,
+{
+    (a, b)
+}
+
+fn main() {
+}
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
new file mode 100644
index 00000000000..f6d611517bc
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ret-impl-trait-one.rs:12:65
+   |
+LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
+   |                                           ------                ^^^^^^^^^^^^^^
+   |                                           |                     |
+   |                                           |                     ...but data from `b` is returned here
+   |                                           this parameter and the return type are declared with different lifetimes...
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs
new file mode 100644
index 00000000000..98da90161e5
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs
@@ -0,0 +1,46 @@
+// edition:2018
+
+// Test that we get the expected borrow check errors when an async
+// function (which takes multiple lifetimes) only returns data from
+// one of them.
+
+#![feature(async_await)]
+
+async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 {
+    a
+}
+
+// Both are borrowed whilst the future is live.
+async fn future_live() {
+    let mut a = 22;
+    let mut b = 44;
+    let future = multiple_named_lifetimes(&a, &b);
+    a += 1; //~ ERROR cannot assign
+    b += 1; //~ ERROR cannot assign
+    let p = future.await;
+    drop(p);
+}
+
+// Just the return value is live after future is awaited.
+async fn just_return_live() {
+    let mut a = 22;
+    let mut b = 44;
+    let future = multiple_named_lifetimes(&a, &b);
+    let p = future.await;
+    a += 1; //~ ERROR cannot assign
+    b += 1;
+    drop(p);
+}
+
+// Once `p` is dead, both `a` and `b` are unborrowed.
+async fn after_both_dead() {
+    let mut a = 22;
+    let mut b = 44;
+    let future = multiple_named_lifetimes(&a, &b);
+    let p = future.await;
+    drop(p);
+    a += 1;
+    b += 1;
+}
+
+fn main() { }
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr
new file mode 100644
index 00000000000..fe70d35942c
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr
@@ -0,0 +1,37 @@
+error[E0506]: cannot assign to `a` because it is borrowed
+  --> $DIR/ret-ref.rs:18:5
+   |
+LL |     let future = multiple_named_lifetimes(&a, &b);
+   |                                           -- borrow of `a` occurs here
+LL |     a += 1;
+   |     ^^^^^^ assignment to borrowed `a` occurs here
+LL |     b += 1;
+LL |     let p = future.await;
+   |             ------ borrow later used here
+
+error[E0506]: cannot assign to `b` because it is borrowed
+  --> $DIR/ret-ref.rs:19:5
+   |
+LL |     let future = multiple_named_lifetimes(&a, &b);
+   |                                               -- borrow of `b` occurs here
+LL |     a += 1;
+LL |     b += 1;
+   |     ^^^^^^ assignment to borrowed `b` occurs here
+LL |     let p = future.await;
+   |             ------ borrow later used here
+
+error[E0506]: cannot assign to `a` because it is borrowed
+  --> $DIR/ret-ref.rs:30:5
+   |
+LL |     let future = multiple_named_lifetimes(&a, &b);
+   |                                           -- borrow of `a` occurs here
+LL |     let p = future.await;
+LL |     a += 1;
+   |     ^^^^^^ assignment to borrowed `a` occurs here
+LL |     b += 1;
+LL |     drop(p);
+   |          - borrow later used here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/async-await/multiple-lifetimes/variance.rs b/src/test/ui/async-await/multiple-lifetimes/variance.rs
new file mode 100644
index 00000000000..b52ad17d563
--- /dev/null
+++ b/src/test/ui/async-await/multiple-lifetimes/variance.rs
@@ -0,0 +1,18 @@
+// edition:2018
+// run-pass
+
+// Test for async fn where the parameters have distinct lifetime
+// parameters that appear in all possible variances.
+
+#![feature(async_await)]
+
+#[allow(dead_code)]
+async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { }
+
+fn take_any(_: &u8) { }
+fn identify(x: &u8) -> &u8 { x }
+fn give_back() -> &'static u8 { &22 }
+
+fn main() {
+    let _ = lotsa_lifetimes(take_any, identify, give_back);
+}
diff --git a/src/test/ui/async-await/no-unsafe-async.rs b/src/test/ui/async-await/no-unsafe-async.rs
new file mode 100644
index 00000000000..81e0cd799ad
--- /dev/null
+++ b/src/test/ui/async-await/no-unsafe-async.rs
@@ -0,0 +1,11 @@
+// edition:2018
+
+struct S;
+
+impl S {
+    #[cfg(FALSE)]
+    unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found `async`
+}
+
+#[cfg(FALSE)]
+unsafe async fn f() {} //~ ERROR expected one of `extern`, `fn`, or `{`, found `async`
diff --git a/src/test/ui/async-await/no-unsafe-async.stderr b/src/test/ui/async-await/no-unsafe-async.stderr
new file mode 100644
index 00000000000..c339c7c3bf5
--- /dev/null
+++ b/src/test/ui/async-await/no-unsafe-async.stderr
@@ -0,0 +1,14 @@
+error: expected one of `extern` or `fn`, found `async`
+  --> $DIR/no-unsafe-async.rs:7:12
+   |
+LL |     unsafe async fn g() {}
+   |            ^^^^^ expected one of `extern` or `fn` here
+
+error: expected one of `extern`, `fn`, or `{`, found `async`
+  --> $DIR/no-unsafe-async.rs:11:8
+   |
+LL | unsafe async fn f() {}
+   |        ^^^^^ expected one of `extern`, `fn`, or `{` here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/attributes/attr-before-view-item.rs b/src/test/ui/attributes/attr-before-view-item.rs
index fc040bd1a5d..e1588aadab6 100644
--- a/src/test/ui/attributes/attr-before-view-item.rs
+++ b/src/test/ui/attributes/attr-before-view-item.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/attributes/attr-before-view-item2.rs b/src/test/ui/attributes/attr-before-view-item2.rs
index c7fad3802e9..c1f667372f5 100644
--- a/src/test/ui/attributes/attr-before-view-item2.rs
+++ b/src/test/ui/attributes/attr-before-view-item2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/attributes/attr-mix-new.rs b/src/test/ui/attributes/attr-mix-new.rs
index d9cb5510960..8119df0c40c 100644
--- a/src/test/ui/attributes/attr-mix-new.rs
+++ b/src/test/ui/attributes/attr-mix-new.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/attributes/class-attributes-1.rs b/src/test/ui/attributes/class-attributes-1.rs
index 7808367f2c1..027b701e591 100644
--- a/src/test/ui/attributes/class-attributes-1.rs
+++ b/src/test/ui/attributes/class-attributes-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pp-exact - Make sure we actually print the attributes
 
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/attributes/class-attributes-2.rs b/src/test/ui/attributes/class-attributes-2.rs
index 348c70f35c3..6aba6b89427 100644
--- a/src/test/ui/attributes/class-attributes-2.rs
+++ b/src/test/ui/attributes/class-attributes-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/attributes/item-attributes.rs b/src/test/ui/attributes/item-attributes.rs
index 72c9a35dc07..c760a28ecf0 100644
--- a/src/test/ui/attributes/item-attributes.rs
+++ b/src/test/ui/attributes/item-attributes.rs
@@ -2,7 +2,7 @@
 // for completeness since .rs files linked from .rc files support this
 // notation to specify their module's attributes
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/attributes/method-attributes.rs b/src/test/ui/attributes/method-attributes.rs
index 2d608acc71f..67439718bd3 100644
--- a/src/test/ui/attributes/method-attributes.rs
+++ b/src/test/ui/attributes/method-attributes.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pp-exact - Make sure we print all the attributes
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/attributes/variant-attributes.rs b/src/test/ui/attributes/variant-attributes.rs
index a910340f4a0..ffcdeb52a04 100644
--- a/src/test/ui/attributes/variant-attributes.rs
+++ b/src/test/ui/attributes/variant-attributes.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pp-exact - Make sure we actually print the attributes
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/bastion-of-the-turbofish.rs b/src/test/ui/bastion-of-the-turbofish.rs
index 0716fcf7f26..cc43210d8e3 100644
--- a/src/test/ui/bastion-of-the-turbofish.rs
+++ b/src/test/ui/bastion-of-the-turbofish.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Bastion of the Turbofish
 // ------------------------
diff --git a/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
index 6d91fd3508a..1d98067ce73 100644
--- a/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
+++ b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
 // (for ensuring that NLL respects user-provided lifetime annotations)
diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs
index 5d084248a7f..a4d6e9b777f 100644
--- a/src/test/ui/check_match/issue-43253.rs
+++ b/src/test/ui/check_match/issue-43253.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(exclusive_range_pattern)]
 #![warn(unreachable_patterns)]
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs b/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs
index 1bfaecd16c0..5f02e642def 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
index 3e42284b72c..0ee738c2c2f 100644
--- a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
+++ b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn with_closure<F, A>(_: F)
     where F: FnOnce(A, &u32)
diff --git a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
index cf417d7c2a8..15711da4b0f 100644
--- a/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
+++ b/src/test/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn with_closure<F, A>(_: F)
     where F: FnOnce(A, &u32)
diff --git a/src/test/ui/closure-expected-type/issue-24421.rs b/src/test/ui/closure-expected-type/issue-24421.rs
index 477eb40c57e..f7b4f2b2454 100644
--- a/src/test/ui/closure-expected-type/issue-24421.rs
+++ b/src/test/ui/closure-expected-type/issue-24421.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn test<F: Fn(&u64, &u64)>(f: F) {}
 
diff --git a/src/test/ui/closure_promotion.rs b/src/test/ui/closure_promotion.rs
index db9c0a6ef3b..db36985afe7 100644
--- a/src/test/ui/closure_promotion.rs
+++ b/src/test/ui/closure_promotion.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(const_err)]
 
diff --git a/src/test/ui/codemap_tests/unicode_3.rs b/src/test/ui/codemap_tests/unicode_3.rs
index ff6d54468b8..b9bcc1b88a3 100644
--- a/src/test/ui/codemap_tests/unicode_3.rs
+++ b/src/test/ui/codemap_tests/unicode_3.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
index 81723bb15b7..f005245e6dc 100644
--- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(never_type)]
 #![allow(unreachable_code)]
diff --git a/src/test/ui/coherence/coherence-subtyping.rs b/src/test/ui/coherence/coherence-subtyping.rs
index e7406757806..a0ff580671a 100644
--- a/src/test/ui/coherence/coherence-subtyping.rs
+++ b/src/test/ui/coherence/coherence-subtyping.rs
@@ -5,7 +5,7 @@
 // universe transition (#56105) may eventually become an error.
 
 // revisions: old re
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![cfg_attr(re, feature(re_rebalance_coherence))]
 
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs
index a0303142622..22517f9da2e 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct.rs
@@ -2,7 +2,7 @@
 // `MyType: !MyTrait` along with other "fundamental" wrappers.
 
 // aux-build:coherence_copy_like_lib.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // skip-codgen
 // revisions: old re
 
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
index f1ab2f0f946..0c7e7cad035 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs
@@ -1,7 +1,7 @@
 // Test that cfg_attr doesn't emit any attributes when the
 // configuration variable is false. This mirrors `cfg-attr-multi-true.rs`
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_must_use)]
 
diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
index 86524e8bd28..645e4e71dfe 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
+++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs
@@ -2,7 +2,7 @@
 // This is done by emitting two attributes that cause new warnings, and then
 // triggering those warnings.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_must_use)]
 
diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
index f592e486be9..cb40734c1d2 100644
--- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
+++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issue-60818-struct-constructors.rs
index 0b4aeae7a4a..b810efe7384 100644
--- a/src/test/ui/const-generics/issue-60818-struct-constructors.rs
+++ b/src/test/ui/const-generics/issue-60818-struct-constructors.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
diff --git a/src/test/ui/consts/const-block-non-item-statement.rs b/src/test/ui/consts/const-block-non-item-statement.rs
index 5ecf9a04984..9aec8552695 100644
--- a/src/test/ui/consts/const-block-non-item-statement.rs
+++ b/src/test/ui/consts/const-block-non-item-statement.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 enum Foo {
     Bar = { let x = 1; 3 }
diff --git a/src/test/ui/consts/const-eval/const_prop_errors.rs b/src/test/ui/consts/const-eval/const_prop_errors.rs
index 51b50b2e75f..48cfea82bd6 100644
--- a/src/test/ui/consts/const-eval/const_prop_errors.rs
+++ b/src/test/ui/consts/const-eval/const_prop_errors.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub trait Foo {
     fn foo(self) -> u32;
diff --git a/src/test/ui/consts/const-eval/const_signed_pat.rs b/src/test/ui/consts/const-eval/const_signed_pat.rs
index cb4fb46bd05..d209e604486 100644
--- a/src/test/ui/consts/const-eval/const_signed_pat.rs
+++ b/src/test/ui/consts/const-eval/const_signed_pat.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     const MIN: i8 = -5;
diff --git a/src/test/ui/consts/const-eval/double_check.rs b/src/test/ui/consts/const-eval/double_check.rs
index 9ac511767c0..2cf6a5494dd 100644
--- a/src/test/ui/consts/const-eval/double_check.rs
+++ b/src/test/ui/consts/const-eval/double_check.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 enum Foo {
     A = 5,
diff --git a/src/test/ui/consts/const-eval/double_promotion.rs b/src/test/ui/consts/const-eval/double_promotion.rs
index 0e75ea8e66b..a9a3f071bf8 100644
--- a/src/test/ui/consts/const-eval/double_promotion.rs
+++ b/src/test/ui/consts/const-eval/double_promotion.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(const_fn, rustc_attrs)]
 
diff --git a/src/test/ui/consts/const-eval/duration_conversion.rs b/src/test/ui/consts/const-eval/duration_conversion.rs
index 854f97d4754..029d4e5e373 100644
--- a/src/test/ui/consts/const-eval/duration_conversion.rs
+++ b/src/test/ui/consts/const-eval/duration_conversion.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::time::Duration;
 
diff --git a/src/test/ui/consts/const-eval/extern_fat_pointer.rs b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
index f8e6fd09c7e..e2b3bc83c3f 100644
--- a/src/test/ui/consts/const-eval/extern_fat_pointer.rs
+++ b/src/test/ui/consts/const-eval/extern_fat_pointer.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(extern_types)]
 
diff --git a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
index 2ad1a633d12..ce0e11f29f4 100644
--- a/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
+++ b/src/test/ui/consts/const-eval/ice-generic-assoc-const.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub trait Nullable {
     const NULL: Self;
diff --git a/src/test/ui/consts/const-eval/ice-packed.rs b/src/test/ui/consts/const-eval/ice-packed.rs
index b9fe4eadd41..250bf954e9a 100644
--- a/src/test/ui/consts/const-eval/ice-packed.rs
+++ b/src/test/ui/consts/const-eval/ice-packed.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #[derive(Copy, Clone, PartialEq, Eq)]
 #[repr(packed)]
 pub struct Num(u64);
diff --git a/src/test/ui/consts/const-eval/issue-47971.rs b/src/test/ui/consts/const-eval/issue-47971.rs
index 9d7b05cd232..9de150bd052 100644
--- a/src/test/ui/consts/const-eval/issue-47971.rs
+++ b/src/test/ui/consts/const-eval/issue-47971.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct S(pub &'static u32, pub u32);
 
diff --git a/src/test/ui/consts/const-eval/issue-50706.rs b/src/test/ui/consts/const-eval/issue-50706.rs
index cb45b86cd7b..bf69bc28da4 100644
--- a/src/test/ui/consts/const-eval/issue-50706.rs
+++ b/src/test/ui/consts/const-eval/issue-50706.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub struct Stats;
 
diff --git a/src/test/ui/consts/const-eval/issue-51300.rs b/src/test/ui/consts/const-eval/issue-51300.rs
index 72a6072e4b7..4753bf0f7b1 100644
--- a/src/test/ui/consts/const-eval/issue-51300.rs
+++ b/src/test/ui/consts/const-eval/issue-51300.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // https://github.com/rust-lang/rust/issues/51300
 
 #[derive(PartialEq, Eq, Clone, Copy)]
diff --git a/src/test/ui/consts/const-eval/issue-53157.rs b/src/test/ui/consts/const-eval/issue-53157.rs
index b9958609971..ac0940b33e4 100644
--- a/src/test/ui/consts/const-eval/issue-53157.rs
+++ b/src/test/ui/consts/const-eval/issue-53157.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 macro_rules! m {
     () => {{
diff --git a/src/test/ui/consts/const-eval/issue-53401.rs b/src/test/ui/consts/const-eval/issue-53401.rs
index e8ac5a90880..d300e0b5125 100644
--- a/src/test/ui/consts/const-eval/issue-53401.rs
+++ b/src/test/ui/consts/const-eval/issue-53401.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub const STATIC_TRAIT: &dyn Test = &();
 
diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs
index 611fb89341d..d04570c67ff 100644
--- a/src/test/ui/consts/const-eval/issue-55541.rs
+++ b/src/test/ui/consts/const-eval/issue-55541.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that we can handle newtypes wrapping extern types
 
diff --git a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
index 0d14cf0f6d9..cea367528c9 100644
--- a/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
+++ b/src/test/ui/consts/const-eval/no_lint_for_statically_known_error.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // if `X` were used instead of `x`, `X - 10` would result in a lint.
 // This file should never produce a lint, no matter how the const
diff --git a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
index 34f61ed5a34..ca75d65a39a 100644
--- a/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
+++ b/src/test/ui/consts/const-eval/promote_mutable_zst_mir_borrowck.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub fn main() {
     let y: &'static mut [u8; 0] = &mut [];
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index ebf80e7d2e6..fa8859cbb3b 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -1,19 +1,23 @@
-#![warn(const_err)]
-
-// compile-pass
 // compile-flags: -O
+
+#![deny(const_err)]
+
 fn main() {
     println!("{}", 0u32 - 1);
     let _x = 0u32 - 1;
-    //~^ WARN const_err
+    //~^ ERROR this expression will panic at runtime [const_err]
     println!("{}", 1/(1-1));
-    //~^ WARN const_err
+    //~^ ERROR this expression will panic at runtime [const_err]
+    //~| ERROR attempt to divide by zero [const_err]
+    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
     let _x = 1/(1-1);
-    //~^ WARN const_err
-    //~| WARN const_err
+    //~^ ERROR const_err
+    //~| ERROR const_err
     println!("{}", 1/(false as u32));
-    //~^ WARN const_err
+    //~^ ERROR this expression will panic at runtime [const_err]
+    //~| ERROR attempt to divide by zero [const_err]
+    //~| ERROR reaching this expression at runtime will panic or abort [const_err]
     let _x = 1/(false as u32);
-    //~^ WARN const_err
-    //~| WARN const_err
+    //~^ ERROR const_err
+    //~| ERROR const_err
 }
diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr
index c9f3a7659f9..12407accf09 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.stderr
@@ -1,72 +1,74 @@
-warning: this expression will panic at runtime
+error: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:7:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^ attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/promoted_errors.rs:1:9
+  --> $DIR/promoted_errors.rs:3:9
    |
-LL | #![warn(const_err)]
+LL | #![deny(const_err)]
    |         ^^^^^^^^^
 
-warning: attempt to divide by zero
+error: attempt to divide by zero
   --> $DIR/promoted_errors.rs:9:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^
 
-warning: this expression will panic at runtime
+error: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:9:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^ attempt to divide by zero
 
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:11:14
+error: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:13:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
-warning: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:11:14
+error: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:13:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^ attempt to divide by zero
 
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:14:20
+error: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^
 
-warning: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:14:20
+error: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
 
-warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:16:14
+error: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:20:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^
 
-warning: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:16:14
+error: this expression will panic at runtime
+  --> $DIR/promoted_errors.rs:20:14
    |
 LL |     let _x = 1/(false as u32);
    |              ^^^^^^^^^^^^^^^^ attempt to divide by zero
 
-warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:14:20
+error: reaching this expression at runtime will panic or abort
+  --> $DIR/promoted_errors.rs:16:20
    |
 LL |     println!("{}", 1/(false as u32));
    |                    ^^^^^^^^^^^^^^^^ attempt to divide by zero
 
-warning: reaching this expression at runtime will panic or abort
+error: reaching this expression at runtime will panic or abort
   --> $DIR/promoted_errors.rs:9:20
    |
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^ attempt to divide by zero
 
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/consts/const-eval/pub_const_err.rs b/src/test/ui/consts/const-eval/pub_const_err.rs
index d882dad295b..4ff140fee7a 100644
--- a/src/test/ui/consts/const-eval/pub_const_err.rs
+++ b/src/test/ui/consts/const-eval/pub_const_err.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![warn(const_err)]
 
 #![crate_type = "lib"]
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.rs b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
index dee09b70d93..7f1586336e7 100644
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.rs
+++ b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![warn(const_err)]
 
 pub const Z: u32 = 0 - 1;
diff --git a/src/test/ui/consts/const-eval/simple_with_undef.rs b/src/test/ui/consts/const-eval/simple_with_undef.rs
index 61398f3a375..8a9f3fe974d 100644
--- a/src/test/ui/consts/const-eval/simple_with_undef.rs
+++ b/src/test/ui/consts/const-eval/simple_with_undef.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 const PARSE_BOOL: Option<&'static str> = None;
 static FOO: (Option<&str>, u32) = (PARSE_BOOL, 42);
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
index a195e12defc..30bd4721923 100644
--- a/src/test/ui/consts/const-eval/valid-const.rs
+++ b/src/test/ui/consts/const-eval/valid-const.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Some constants that *are* valid
 #![feature(const_transmute)]
diff --git a/src/test/ui/consts/const-eval/zst_operand_eval.rs b/src/test/ui/consts/const-eval/zst_operand_eval.rs
index d837da1066d..7edb6bd03da 100644
--- a/src/test/ui/consts/const-eval/zst_operand_eval.rs
+++ b/src/test/ui/consts/const-eval/zst_operand_eval.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 static ASSERT: () = [()][!(std::mem::size_of::<u32>() == 4) as usize];
 
diff --git a/src/test/ui/consts/const-expr-addr-operator.rs b/src/test/ui/consts/const-expr-addr-operator.rs
index dc9f292c2b8..37bf24c2fbe 100644
--- a/src/test/ui/consts/const-expr-addr-operator.rs
+++ b/src/test/ui/consts/const-expr-addr-operator.rs
@@ -1,5 +1,5 @@
 // Encountered while testing #44614.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub fn main() {
     // Constant of generic type (int)
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs
index dcf89f90e31..d2c89cb54a0 100644
--- a/src/test/ui/consts/const-fn-destructuring-arg.rs
+++ b/src/test/ui/consts/const-fn-destructuring-arg.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 const fn i((a, b): (u32, u32)) -> u32 {
     a + b
diff --git a/src/test/ui/consts/const-nonzero.rs b/src/test/ui/consts/const-nonzero.rs
index c06ab227f64..6db3d1b3331 100644
--- a/src/test/ui/consts/const-nonzero.rs
+++ b/src/test/ui/consts/const-nonzero.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::num::NonZeroU8;
 
diff --git a/src/test/ui/consts/const-pattern-not-const-evaluable.rs b/src/test/ui/consts/const-pattern-not-const-evaluable.rs
index 8dd78ca0ba4..dae5343fe30 100644
--- a/src/test/ui/consts/const-pattern-not-const-evaluable.rs
+++ b/src/test/ui/consts/const-pattern-not-const-evaluable.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[derive(PartialEq, Eq)]
 enum Cake {
diff --git a/src/test/ui/consts/const-validation-fail-55455.rs b/src/test/ui/consts/const-validation-fail-55455.rs
index def4062339f..583074888c9 100644
--- a/src/test/ui/consts/const-validation-fail-55455.rs
+++ b/src/test/ui/consts/const-validation-fail-55455.rs
@@ -1,5 +1,5 @@
 // https://github.com/rust-lang/rust/issues/55454
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct This<T>(T);
 
diff --git a/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs
index c7617c9c7ad..d22c789609f 100644
--- a/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs
+++ b/src/test/ui/consts/const_fn_return_nested_fn_ptr.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:const_fn_lib.rs
 
 extern crate const_fn_lib;
diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs
index 0b09b8469fd..343fcb4859b 100644
--- a/src/test/ui/consts/const_let_assign.rs
+++ b/src/test/ui/consts/const_let_assign.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct S(i32);
 
diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs
index 1c44237e49b..4787c1750d2 100644
--- a/src/test/ui/consts/const_let_assign2.rs
+++ b/src/test/ui/consts/const_let_assign2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub struct AA {
     pub data: [u8; 10],
diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs
index c48f54e567b..0c927a0484d 100644
--- a/src/test/ui/consts/const_let_eq_float.rs
+++ b/src/test/ui/consts/const_let_eq_float.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(const_fn)]
 
diff --git a/src/test/ui/consts/const_let_irrefutable.rs b/src/test/ui/consts/const_let_irrefutable.rs
index 424a16f7ed3..e889abf4abe 100644
--- a/src/test/ui/consts/const_let_irrefutable.rs
+++ b/src/test/ui/consts/const_let_irrefutable.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {}
 
diff --git a/src/test/ui/consts/drop_none.rs b/src/test/ui/consts/drop_none.rs
index 86a197ffb99..9d98d3be874 100644
--- a/src/test/ui/consts/drop_none.rs
+++ b/src/test/ui/consts/drop_none.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct A;
 impl Drop for A {
diff --git a/src/test/ui/consts/int_ptr_for_zst_slices.rs b/src/test/ui/consts/int_ptr_for_zst_slices.rs
index afa2c6a5b9e..34dafd00d28 100644
--- a/src/test/ui/consts/int_ptr_for_zst_slices.rs
+++ b/src/test/ui/consts/int_ptr_for_zst_slices.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(const_raw_ptr_deref)]
 
diff --git a/src/test/ui/consts/invalid_promotion.rs b/src/test/ui/consts/invalid_promotion.rs
index f98406e50e9..a31eaf40e0e 100644
--- a/src/test/ui/consts/invalid_promotion.rs
+++ b/src/test/ui/consts/invalid_promotion.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // note this was only reproducible with lib crates
 // compile-flags: --crate-type=lib
 
diff --git a/src/test/ui/consts/issue-62045.rs b/src/test/ui/consts/issue-62045.rs
index 9f41ed9a245..efeb9fc551c 100644
--- a/src/test/ui/consts/issue-62045.rs
+++ b/src/test/ui/consts/issue-62045.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     assert_eq!(&mut [0; 1][..], &mut []);
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
index 23bd7332547..cb8f74186bd 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::cell::UnsafeCell;
 use std::sync::atomic::AtomicU32;
diff --git a/src/test/ui/consts/promote_evaluation_unused_result.rs b/src/test/ui/consts/promote_evaluation_unused_result.rs
index dc21b9fe8cd..4eda785bb89 100644
--- a/src/test/ui/consts/promote_evaluation_unused_result.rs
+++ b/src/test/ui/consts/promote_evaluation_unused_result.rs
@@ -1,4 +1,4 @@
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
 
diff --git a/src/test/ui/consts/promote_fn_calls.rs b/src/test/ui/consts/promote_fn_calls.rs
index 6b6eea36361..8995aaacd85 100644
--- a/src/test/ui/consts/promote_fn_calls.rs
+++ b/src/test/ui/consts/promote_fn_calls.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:promotable_const_fn_lib.rs
 
 extern crate promotable_const_fn_lib;
diff --git a/src/test/ui/consts/promote_fn_calls_std.rs b/src/test/ui/consts/promote_fn_calls_std.rs
index d982f350208..bdb472f3a9c 100644
--- a/src/test/ui/consts/promote_fn_calls_std.rs
+++ b/src/test/ui/consts/promote_fn_calls_std.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let x: &'static u8 = &u8::max_value();
diff --git a/src/test/ui/consts/promoted-validation-55454.rs b/src/test/ui/consts/promoted-validation-55454.rs
index 5e193b1b7de..23cae4fb57d 100644
--- a/src/test/ui/consts/promoted-validation-55454.rs
+++ b/src/test/ui/consts/promoted-validation-55454.rs
@@ -1,5 +1,5 @@
 // https://github.com/rust-lang/rust/issues/55454
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[derive(PartialEq)]
 struct This<T>(T);
diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs
index 68b9a20ecf9..d57036ae58f 100644
--- a/src/test/ui/consts/promoted_regression.rs
+++ b/src/test/ui/consts/promoted_regression.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _ = &[("", ""); 3];
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs
index 27e1a111163..df09c76c558 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
 
diff --git a/src/test/ui/consts/std/slice.rs b/src/test/ui/consts/std/slice.rs
index ad38105b6aa..f19defc64dd 100644
--- a/src/test/ui/consts/std/slice.rs
+++ b/src/test/ui/consts/std/slice.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Wrap<T>(T);
 unsafe impl<T> Send for Wrap<T> {}
diff --git a/src/test/ui/consts/underscore_const_names.rs b/src/test/ui/consts/underscore_const_names.rs
index 8d57e5074f1..d0e625bf199 100644
--- a/src/test/ui/consts/underscore_const_names.rs
+++ b/src/test/ui/consts/underscore_const_names.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(unused)]
 
diff --git a/src/test/ui/consts/union_constant.rs b/src/test/ui/consts/union_constant.rs
index 16b05310b9f..508ff7e0ae8 100644
--- a/src/test/ui/consts/union_constant.rs
+++ b/src/test/ui/consts/union_constant.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 union Uninit {
     _never_use: *const u8,
diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs
index 496ce4fb378..92a67950986 100644
--- a/src/test/ui/dead-code-tuple-struct-field.rs
+++ b/src/test/ui/dead-code-tuple-struct-field.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(dead_code)]
 
diff --git a/src/test/ui/deprecation/atomic_initializers.fixed b/src/test/ui/deprecation/atomic_initializers.fixed
index dee1d979cff..363bda75f16 100644
--- a/src/test/ui/deprecation/atomic_initializers.fixed
+++ b/src/test/ui/deprecation/atomic_initializers.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[allow(deprecated, unused_imports)]
 use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
diff --git a/src/test/ui/deprecation/atomic_initializers.rs b/src/test/ui/deprecation/atomic_initializers.rs
index b9e25e817bc..00c5f7b0b12 100644
--- a/src/test/ui/deprecation/atomic_initializers.rs
+++ b/src/test/ui/deprecation/atomic_initializers.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[allow(deprecated, unused_imports)]
 use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs
index 4980a7f5aa3..ed4055ecdd3 100644
--- a/src/test/ui/deprecation/derive_on_deprecated.rs
+++ b/src/test/ui/deprecation/derive_on_deprecated.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(deprecated)]
 
diff --git a/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
index 235146bad9c..3fd43466467 100644
--- a/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
+++ b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![forbid(deprecated)]
 
diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs
index b314eacc92e..2c4d64e4e60 100644
--- a/src/test/ui/derive-uninhabited-enum-38885.rs
+++ b/src/test/ui/derive-uninhabited-enum-38885.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Wunused
 
 // ensure there are no special warnings about uninhabited types
diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
index f535791d7fb..cf14aef7900 100644
--- a/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
+++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-decl-macros-unlinted.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Under the 2015 edition with the keyword_idents lint, `dyn` is
 // not entirely acceptable as an identifier.
diff --git a/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
index 27e49055868..0d85b87dee5 100644
--- a/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
+++ b/src/test/ui/dyn-keyword/dyn-2015-idents-in-macros-unlinted.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Under the 2015 edition with the keyword_idents lint, `dyn` is
 // not entirely acceptable as an identifier.
diff --git a/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
index 8cef5c2b349..2a8b6b24831 100644
--- a/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
+++ b/src/test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs
@@ -1,7 +1,7 @@
 // Under the 2015 edition without the keyword_idents lint, `dyn` is
 // entirely acceptable as an identifier.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
index ff3830d6175..2718e89a3f2 100644
--- a/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
+++ b/src/test/ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // rust-lang/rust#56327: Some occurrences of `dyn` within a macro are
 // not instances of identifiers, and thus should *not* be caught by the
diff --git a/src/test/ui/editions/edition-extern-crate-allowed.rs b/src/test/ui/editions/edition-extern-crate-allowed.rs
index 6361fff6ff4..93fe69e0af2 100644
--- a/src/test/ui/editions/edition-extern-crate-allowed.rs
+++ b/src/test/ui/editions/edition-extern-crate-allowed.rs
@@ -1,6 +1,6 @@
 // aux-build:edition-extern-crate-allowed.rs
 // edition:2015
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_idioms)]
 
diff --git a/src/test/ui/editions/edition-feature-ok.rs b/src/test/ui/editions/edition-feature-ok.rs
index c2468df4939..12642132694 100644
--- a/src/test/ui/editions/edition-feature-ok.rs
+++ b/src/test/ui/editions/edition-feature-ok.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rust_2018_preview)]
 
diff --git a/src/test/ui/editions/edition-feature-redundant.rs b/src/test/ui/editions/edition-feature-redundant.rs
index 87a2a22105f..4309a777d33 100644
--- a/src/test/ui/editions/edition-feature-redundant.rs
+++ b/src/test/ui/editions/edition-feature-redundant.rs
@@ -1,5 +1,5 @@
 // edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rust_2018_preview)]
 //~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition
diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
index 940b0c3c63d..310bff21d18 100644
--- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
+++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // compile-flags:--extern edition_imports_2015
 // aux-build:edition-imports-2015.rs
diff --git a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
index c3757ab1934..9c3beb1ce58 100644
--- a/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
+++ b/src/test/ui/editions/edition-keywords-2015-2015-expansion.rs
@@ -1,6 +1,6 @@
 // edition:2015
 // aux-build:edition-kw-macro-2015.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(keyword_idents)]
 
diff --git a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
index 6a30c498219..619e6424db4 100644
--- a/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
+++ b/src/test/ui/editions/edition-keywords-2018-2015-expansion.rs
@@ -1,6 +1,6 @@
 // edition:2018
 // aux-build:edition-kw-macro-2015.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(keyword_idents)]
 
diff --git a/src/test/ui/emit-artifact-notifications.rs b/src/test/ui/emit-artifact-notifications.rs
index c2c930c8b1b..d309485f053 100644
--- a/src/test/ui/emit-artifact-notifications.rs
+++ b/src/test/ui/emit-artifact-notifications.rs
@@ -1,5 +1,7 @@
 // compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
 
 // A very basic test for the emission of artifact notifications in JSON output.
 
diff --git a/src/test/ui/error-codes/E0705.rs b/src/test/ui/error-codes/E0705.rs
index cc2b8f64d9f..4e32ef35560 100644
--- a/src/test/ui/error-codes/E0705.rs
+++ b/src/test/ui/error-codes/E0705.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This is a stub feature that doesn't control anything, so to make tidy happy,
 // gate-test-test_2018_feature
diff --git a/src/test/ui/existential_types/bound_reduction.rs b/src/test/ui/existential_types/bound_reduction.rs
index c1c0c60d59e..46bc17293bc 100644
--- a/src/test/ui/existential_types/bound_reduction.rs
+++ b/src/test/ui/existential_types/bound_reduction.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/existential_types/cross_crate_ice.rs b/src/test/ui/existential_types/cross_crate_ice.rs
index c5d5ca916a4..c30608176aa 100644
--- a/src/test/ui/existential_types/cross_crate_ice.rs
+++ b/src/test/ui/existential_types/cross_crate_ice.rs
@@ -1,5 +1,5 @@
 // aux-build:cross_crate_ice.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 extern crate cross_crate_ice;
 
diff --git a/src/test/ui/existential_types/cross_crate_ice2.rs b/src/test/ui/existential_types/cross_crate_ice2.rs
index a0f3933ce33..3a7e490260f 100644
--- a/src/test/ui/existential_types/cross_crate_ice2.rs
+++ b/src/test/ui/existential_types/cross_crate_ice2.rs
@@ -1,5 +1,5 @@
 // aux-build:cross_crate_ice2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 extern crate cross_crate_ice2;
 
diff --git a/src/test/ui/existential_types/different_defining_uses_never_type2.rs b/src/test/ui/existential_types/different_defining_uses_never_type2.rs
index 2953f1745ee..0f02cfaad7e 100644
--- a/src/test/ui/existential_types/different_defining_uses_never_type2.rs
+++ b/src/test/ui/existential_types/different_defining_uses_never_type2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(existential_type)]
 
diff --git a/src/test/ui/existential_types/existential-associated-type.rs b/src/test/ui/existential_types/existential-associated-type.rs
index 299ae91b843..bfb91f68ffd 100644
--- a/src/test/ui/existential_types/existential-associated-type.rs
+++ b/src/test/ui/existential_types/existential-associated-type.rs
@@ -1,5 +1,5 @@
 #![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Bar {}
 struct Dummy;
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use10.rs b/src/test/ui/existential_types/generic_duplicate_param_use10.rs
index 10f2c630582..0d9c7cdfe71 100644
--- a/src/test/ui/existential_types/generic_duplicate_param_use10.rs
+++ b/src/test/ui/existential_types/generic_duplicate_param_use10.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(existential_type)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/existential_types/generic_duplicate_param_use7.rs b/src/test/ui/existential_types/generic_duplicate_param_use7.rs
index 5d8d05c3087..56e1528c213 100644
--- a/src/test/ui/existential_types/generic_duplicate_param_use7.rs
+++ b/src/test/ui/existential_types/generic_duplicate_param_use7.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(existential_type)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/existential_types/generic_lifetime_param.rs b/src/test/ui/existential_types/generic_lifetime_param.rs
index a8bb0229f0e..1ea01f17b70 100644
--- a/src/test/ui/existential_types/generic_lifetime_param.rs
+++ b/src/test/ui/existential_types/generic_lifetime_param.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(existential_type)]
 
diff --git a/src/test/ui/existential_types/nested_existential_types.rs b/src/test/ui/existential_types/nested_existential_types.rs
index 6d2a12da7e4..de52e88bae2 100644
--- a/src/test/ui/existential_types/nested_existential_types.rs
+++ b/src/test/ui/existential_types/nested_existential_types.rs
@@ -1,5 +1,5 @@
 #![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 mod my_mod {
   use std::fmt::Debug;
 
diff --git a/src/test/ui/existential_types/private_unused.rs b/src/test/ui/existential_types/private_unused.rs
index 736d812bc0a..92268f1861d 100644
--- a/src/test/ui/existential_types/private_unused.rs
+++ b/src/test/ui/existential_types/private_unused.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[deny(warnings)]
 
diff --git a/src/test/ui/explain.rs b/src/test/ui/explain.rs
index 3622ba77645..28973d67564 100644
--- a/src/test/ui/explain.rs
+++ b/src/test/ui/explain.rs
@@ -1,2 +1,2 @@
 // compile-flags: --explain E0591
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
diff --git a/src/test/ui/extern-prelude.rs b/src/test/ui/extern-prelude.rs
index 0e52f2c5158..50fed6034aa 100644
--- a/src/test/ui/extern-prelude.rs
+++ b/src/test/ui/extern-prelude.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:--extern extern_prelude --extern Vec
 // aux-build:extern-prelude.rs
 // aux-build:extern-prelude-vec.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
index 98ca3444c91..dab946bb818 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
@@ -3,7 +3,7 @@
 // `#![macro_escape]` is incompatible with crate-level `#![macro_use]`
 // already present in issue-43106-gating-of-builtin-attrs.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![macro_escape]
 //~^ WARN macro_escape is a deprecated synonym for macro_use
diff --git a/src/test/ui/feature-gates/feature-gate-const-indexing.rs b/src/test/ui/feature-gates/feature-gate-const-indexing.rs
index 4df1c7d6ed2..2b1067b3489 100644
--- a/src/test/ui/feature-gates/feature-gate-const-indexing.rs
+++ b/src/test/ui/feature-gates/feature-gate-const-indexing.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
diff --git a/src/test/ui/feature-gates/feature-gate-member-constraints.rs b/src/test/ui/feature-gates/feature-gate-member-constraints.rs
new file mode 100644
index 00000000000..293a93352e6
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-member-constraints.rs
@@ -0,0 +1,9 @@
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T {}
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+    //~^ ERROR ambiguous lifetime bound
+    (x, y)
+}
+
+fn main() { }
diff --git a/src/test/ui/feature-gates/feature-gate-member-constraints.stderr b/src/test/ui/feature-gates/feature-gate-member-constraints.stderr
new file mode 100644
index 00000000000..3745d5e1c59
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-member-constraints.stderr
@@ -0,0 +1,10 @@
+error: ambiguous lifetime bound in `impl Trait`
+  --> $DIR/feature-gate-member-constraints.rs:4:43
+   |
+LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> {
+   |                                           ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
+   |
+   = help: add #![feature(member_constraints)] 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 fe3c1e0afdd..03bf933cd08 100644
--- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
@@ -4,7 +4,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [1, 2, ..] => {}
    |                ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error[E0658]: syntax for subslices in slice patterns is not yet stabilized
@@ -13,7 +13,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [1, .., 5] => {}
    |             ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error[E0658]: syntax for subslices in slice patterns is not yet stabilized
@@ -22,7 +22,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [.., 4, 5] => {}
    |          ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error[E0658]: syntax for subslices in slice patterns is not yet stabilized
@@ -31,7 +31,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [ xs.., 4, 5 ] => {}
    |           ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error[E0658]: syntax for subslices in slice patterns is not yet stabilized
@@ -40,7 +40,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [ 1, xs.., 5 ] => {}
    |              ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = help: add #![feature(slice_patterns)] to the crate attributes to enable
 
 error[E0658]: syntax for subslices in slice patterns is not yet stabilized
@@ -49,7 +49,7 @@ error[E0658]: syntax for subslices in slice patterns is not yet stabilized
 LL |         [ 1, 2, xs.. ] => {}
    |                 ^^
    |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/23121
+   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
    = 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-type_alias_enum_variants.rs b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs
deleted file mode 100644
index c7d3304a128..00000000000
--- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-enum Foo {
-    Bar(i32),
-    Baz { i: i32 },
-}
-
-type Alias = Foo;
-
-fn main() {
-    let t = Alias::Bar(0);
-    //~^ ERROR enum variants on type aliases are experimental
-    let t = Alias::Baz { i: 0 };
-    //~^ ERROR enum variants on type aliases are experimental
-    match t {
-        Alias::Bar(_i) => {}
-        //~^ ERROR enum variants on type aliases are experimental
-        Alias::Baz { i: _i } => {}
-        //~^ ERROR enum variants on type aliases are experimental
-    }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr
deleted file mode 100644
index 43535af7c69..00000000000
--- a/src/test/ui/feature-gates/feature-gate-type_alias_enum_variants.stderr
+++ /dev/null
@@ -1,34 +0,0 @@
-error: enum variants on type aliases are experimental
-  --> $DIR/feature-gate-type_alias_enum_variants.rs:9:13
-   |
-LL |     let t = Alias::Bar(0);
-   |             ^^^^^^^^^^
-   |
-   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
-  --> $DIR/feature-gate-type_alias_enum_variants.rs:11:13
-   |
-LL |     let t = Alias::Baz { i: 0 };
-   |             ^^^^^^^^^^
-   |
-   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
-  --> $DIR/feature-gate-type_alias_enum_variants.rs:14:9
-   |
-LL |         Alias::Bar(_i) => {}
-   |         ^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: enum variants on type aliases are experimental
-  --> $DIR/feature-gate-type_alias_enum_variants.rs:16:9
-   |
-LL |         Alias::Baz { i: _i } => {}
-   |         ^^^^^^^^^^
-   |
-   = help: add `#![feature(type_alias_enum_variants)]` to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/fn_must_use.rs b/src/test/ui/fn_must_use.rs
index 8519cf741a3..e4118546616 100644
--- a/src/test/ui/fn_must_use.rs
+++ b/src/test/ui/fn_must_use.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_must_use)]
 
diff --git a/src/test/ui/generator/issue-53548-1.rs b/src/test/ui/generator/issue-53548-1.rs
index df11800731c..395456ce7c6 100644
--- a/src/test/ui/generator/issue-53548-1.rs
+++ b/src/test/ui/generator/issue-53548-1.rs
@@ -2,7 +2,7 @@
 // but which encountered the same ICE/error. See `issue-53548.rs`
 // for details.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::cell::RefCell;
 use std::rc::Rc;
diff --git a/src/test/ui/generator/issue-53548.rs b/src/test/ui/generator/issue-53548.rs
index 73a2bcdd555..8136c65923b 100644
--- a/src/test/ui/generator/issue-53548.rs
+++ b/src/test/ui/generator/issue-53548.rs
@@ -15,7 +15,7 @@
 // also analogous to what we would do for higher-ranked regions
 // appearing within the trait in other positions).
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(generators)]
 
diff --git a/src/test/ui/generic/generic-param-attrs.rs b/src/test/ui/generic/generic-param-attrs.rs
index 601d2a9e0a3..39a600339aa 100644
--- a/src/test/ui/generic/generic-param-attrs.rs
+++ b/src/test/ui/generic/generic-param-attrs.rs
@@ -6,7 +6,7 @@
 // using `rustc_attrs` feature. There is a separate compile-fail/ test
 // ensuring that the attribute feature-gating works in this context.)
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/hello_world/main.rs b/src/test/ui/hello_world/main.rs
index f790af64b4d..22ce47414b2 100644
--- a/src/test/ui/hello_world/main.rs
+++ b/src/test/ui/hello_world/main.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that compiling hello world succeeds with no output of any kind.
 
diff --git a/src/test/ui/hygiene/dollar-crate-modern.rs b/src/test/ui/hygiene/dollar-crate-modern.rs
index 380ad20486e..9c25e138d2c 100644
--- a/src/test/ui/hygiene/dollar-crate-modern.rs
+++ b/src/test/ui/hygiene/dollar-crate-modern.rs
@@ -1,6 +1,6 @@
 // Make sure `$crate` and `crate` work in for basic cases of nested macros.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:intercrate.rs
 
 #![feature(decl_macro, crate_in_paths)]
diff --git a/src/test/ui/hygiene/local_inner_macros.rs b/src/test/ui/hygiene/local_inner_macros.rs
index f4c1a931f68..f361e3d5d49 100644
--- a/src/test/ui/hygiene/local_inner_macros.rs
+++ b/src/test/ui/hygiene/local_inner_macros.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:local_inner_macros.rs
 
 extern crate local_inner_macros;
diff --git a/src/test/ui/hygiene/transparent-basic.rs b/src/test/ui/hygiene/transparent-basic.rs
index 0a86234fdba..23ee558cc17 100644
--- a/src/test/ui/hygiene/transparent-basic.rs
+++ b/src/test/ui/hygiene/transparent-basic.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:transparent-basic.rs
 
 #![feature(decl_macro, rustc_attrs)]
diff --git a/src/test/ui/if/if-let.rs b/src/test/ui/if/if-let.rs
index 741685fe9b6..3447f358d85 100644
--- a/src/test/ui/if/if-let.rs
+++ b/src/test/ui/if/if-let.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn macros() {
     macro_rules! foo{
diff --git a/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs b/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs
index 20d778d20ae..9d7b2f2d088 100644
--- a/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs
+++ b/src/test/ui/impl-header-lifetime-elision/inherent-impl.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Foo<'a>(&'a u8);
 
diff --git a/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs b/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs
index 26bd435cbac..130de9ccf62 100644
--- a/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs
+++ b/src/test/ui/impl-trait/associated-existential-type-generic-trait.rs
@@ -1,5 +1,5 @@
 #![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Bar {}
 struct Dummy<U>(U);
diff --git a/src/test/ui/impl-trait/associated-existential-type-trivial.rs b/src/test/ui/impl-trait/associated-existential-type-trivial.rs
index cc974ffea7b..0e83b4084b6 100644
--- a/src/test/ui/impl-trait/associated-existential-type-trivial.rs
+++ b/src/test/ui/impl-trait/associated-existential-type-trivial.rs
@@ -1,5 +1,5 @@
 #![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Bar {}
 struct Dummy;
diff --git a/src/test/ui/impl-trait/associated-existential-type.rs b/src/test/ui/impl-trait/associated-existential-type.rs
index 38511bd062c..58966aefe1c 100644
--- a/src/test/ui/impl-trait/associated-existential-type.rs
+++ b/src/test/ui/impl-trait/associated-existential-type.rs
@@ -1,5 +1,5 @@
 #![feature(existential_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Bar {}
 struct Dummy;
diff --git a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs
index 90a7519074b..7ae1ac4f576 100644
--- a/src/test/ui/impl-trait/can-return-unconstrained-closure.rs
+++ b/src/test/ui/impl-trait/can-return-unconstrained-closure.rs
@@ -10,7 +10,7 @@
 // concrete type against the bound, which forces the return type to be
 // `&'static i32` here.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn make_identity() -> impl Sized {
     |x: &'static i32| x
diff --git a/src/test/ui/impl-trait/deprecated_annotation.rs b/src/test/ui/impl-trait/deprecated_annotation.rs
index dd9f5fd4647..f76724c8ab1 100644
--- a/src/test/ui/impl-trait/deprecated_annotation.rs
+++ b/src/test/ui/impl-trait/deprecated_annotation.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(warnings)]
 
diff --git a/src/test/ui/impl-trait/existential-minimal.rs b/src/test/ui/impl-trait/existential-minimal.rs
index c93c6a499bc..6d3c0692970 100644
--- a/src/test/ui/impl-trait/existential-minimal.rs
+++ b/src/test/ui/impl-trait/existential-minimal.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {}
 
diff --git a/src/test/ui/impl-trait/existential_type_in_fn_body.rs b/src/test/ui/impl-trait/existential_type_in_fn_body.rs
index b29ae064b76..32fc4a97ef4 100644
--- a/src/test/ui/impl-trait/existential_type_in_fn_body.rs
+++ b/src/test/ui/impl-trait/existential_type_in_fn_body.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(existential_type)]
 
diff --git a/src/test/ui/impl-trait/issues/issue-42479.rs b/src/test/ui/impl-trait/issues/issue-42479.rs
index 2da15ac5b6e..7d69cd0a303 100644
--- a/src/test/ui/impl-trait/issues/issue-42479.rs
+++ b/src/test/ui/impl-trait/issues/issue-42479.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::iter::once;
 
diff --git a/src/test/ui/impl-trait/issues/issue-49376.rs b/src/test/ui/impl-trait/issues/issue-49376.rs
index 13671b8dbf4..12e69b16adf 100644
--- a/src/test/ui/impl-trait/issues/issue-49376.rs
+++ b/src/test/ui/impl-trait/issues/issue-49376.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Tests for nested self-reference which caused a stack overflow.
 
diff --git a/src/test/ui/impl-trait/issues/issue-52128.rs b/src/test/ui/impl-trait/issues/issue-52128.rs
index eb4456a0d59..ac26c10e55d 100644
--- a/src/test/ui/impl-trait/issues/issue-52128.rs
+++ b/src/test/ui/impl-trait/issues/issue-52128.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(warnings)]
 
diff --git a/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs
index 50646edd61a..0c07101bb7b 100644
--- a/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs
+++ b/src/test/ui/impl-trait/issues/issue-55608-captures-empty-region.rs
@@ -1,7 +1,7 @@
 // This used to ICE because it creates an `impl Trait` that captures a
 // hidden empty region.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn server() -> impl FilterBase2 {
     segment2(|| { loop { } }).map2(|| "")
diff --git a/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs b/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs
index 11f1a392239..ed066ce1924 100644
--- a/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs
+++ b/src/test/ui/impl-trait/issues/issue-57464-unexpected-regions.rs
@@ -5,7 +5,7 @@
 // opaque type. As all regions are now required to outlive the bound in an
 // opaque type we avoid the issue here.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct A<F>(F);
 
diff --git a/src/test/ui/impl-trait/multiple-lifetimes.rs b/src/test/ui/impl-trait/multiple-lifetimes.rs
index 8346542135b..92e5ea2f49d 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes.rs
+++ b/src/test/ui/impl-trait/multiple-lifetimes.rs
@@ -1,5 +1,5 @@
 // Test that multiple liftimes are allowed in impl trait types.
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait X<'x>: Sized {}
 
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs
new file mode 100644
index 00000000000..61e858ee02d
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs
@@ -0,0 +1,22 @@
+// compile-flags:-Zborrowck=mir
+
+#![feature(member_constraints)]
+#![feature(existential_type)]
+
+#[derive(Clone)]
+struct CopyIfEq<T, U>(T, U);
+
+impl<T: Copy> Copy for CopyIfEq<T, T> {}
+
+existential type E<'a, 'b>: Sized;
+
+fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+    //~^ ERROR lifetime may not live long enough
+    let v = CopyIfEq::<*mut _, *mut _>(&mut {x}, &mut y);
+    let u = v;
+    let _: *mut &'a i32 = u.1;
+    unsafe { let _: &'b i32 = *u.0; }
+    u.0
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
new file mode 100644
index 00000000000..b59dfbe9f2a
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/error-handling.rs:13:56
+   |
+LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
+   |        -- lifetime `'a` defined here                   ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a constraint
+   |
+LL | existential type E<'a, 'b>: Sized; + 'a
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
new file mode 100644
index 00000000000..2da3886bb55
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs
@@ -0,0 +1,54 @@
+// edition:2018
+// run-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Invert<'a> <: Invert<'b>` if `'b: 'a`, unlike most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Invert<'a>(fn(&'a u8));
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
+where
+    'c: 'a,
+    'c: 'b,
+    'd: 'c,
+{
+    // Representing the where clauses as a graph, where `A: B` is an
+    // edge `B -> A`:
+    //
+    // ```
+    // 'a -> 'c -> 'd
+    //        ^
+    //        |
+    //       'b
+    // ```
+    //
+    // Meanwhile we return a value &'0 u8 where we have the constraints:
+    //
+    // ```
+    // '0: 'a
+    // '0: 'b
+    // '0 in ['d, 'e]
+    // ```
+    //
+    // Here, ignoring the "in" constraint, the minimal choice for `'0`
+    // is `'c`, but that is not in the "in set". Still, that reduces
+    // the range of options in the "in set" to just `'d` (`'e: 'c`
+    // does not hold).
+    let p = if condition() { a } else { b };
+    p
+}
+
+fn condition() -> bool {
+    true
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr
new file mode 100644
index 00000000000..4de872e8441
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr
@@ -0,0 +1,19 @@
+warning[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/inverse-bounds.rs:16:70
+   |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
+   |                                                                      ^^^^^^^^^^^^^^^^^^
+   |
+   = note: hidden type `Invert<'_>` captures lifetime '_#8r
+   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
+   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
+
+warning: the feature `pin` has been stable since 1.33.0 and no longer requires an attribute to enable
+  --> $DIR/inverse-bounds.rs:4:60
+   |
+LL | #![feature(arbitrary_self_types, async_await, await_macro, pin)]
+   |                                                            ^^^
+   |
+   = note: #[warn(stable_features)] on by default
+
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs
new file mode 100644
index 00000000000..5f484773405
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs
@@ -0,0 +1,29 @@
+// edition:2018
+// compile-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Test case where we have elision in the impl trait and we have to
+// pick the right region.
+
+// Ultimately `Trait<'x, 'static>`.
+fn upper_bounds1(a: &u8) -> impl Trait<'_, 'static> {
+    (a, a)
+}
+
+// Ultimately `Trait<'x, 'x>`, so not really multiple bounds.
+fn upper_bounds2(a: &u8) -> impl Trait<'_, '_> {
+    (a, a)
+}
+
+// Kind of a weird annoying case.
+fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> {
+    (a, a)
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-existential.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-existential.rs
new file mode 100644
index 00000000000..c17ae6f0519
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-existential.rs
@@ -0,0 +1,32 @@
+// edition:2018
+// compile-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+#![feature(existential_type)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+existential type Foo<'a, 'b>: Trait<'a, 'b>;
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
+    // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+    //
+    // ```
+    // 'a: '0
+    // 'b: '1
+    // '0 in ['a, 'b]
+    // '1 in ['a, 'b]
+    // ```
+    //
+    // We use the fact that `'a: 0'` must hold (combined with the in
+    // constraint) to determine that `'0 = 'a` must be the answer.
+    (a, b)
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs
new file mode 100644
index 00000000000..31891ef15c7
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs
@@ -0,0 +1,29 @@
+// edition:2018
+// compile-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> { }
+impl<T> Trait<'_, '_> for T { }
+
+// Here we wind up selecting `'a` and `'b` in the hidden type because
+// those are the types that appear in the original values.
+
+fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> {
+    // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
+    //
+    // ```
+    // 'a: '0
+    // 'b: '1
+    // '0 in ['a, 'b]
+    // '1 in ['a, 'b]
+    // ```
+    //
+    // We use the fact that `'a: 0'` must hold (combined with the in
+    // constraint) to determine that `'0 = 'a` must be the answer.
+    (a, b)
+}
+
+fn main() { }
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs
new file mode 100644
index 00000000000..29c997085d8
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs
@@ -0,0 +1,46 @@
+// edition:2018
+// compile-pass
+// revisions: migrate mir
+//[mir]compile-flags: -Z borrowck=mir
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we wind up selecting `'e` in the hidden type because
+// we need something outlived by both `'a` and `'b` and only `'e` applies.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+where
+    'a: 'e,
+    'b: 'e,
+    'a: 'd,
+{
+    // We return a value:
+    //
+    // ```
+    // 'a: '0
+    // 'b: '1
+    // '0 in ['d, 'e]
+    // ```
+    //
+    // but we don't have it.
+    //
+    // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
+    let p = if condition() { a } else { b };
+    p
+}
+
+fn condition() -> bool {
+    true
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr
new file mode 100644
index 00000000000..a255c48ec6e
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr
@@ -0,0 +1,9 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ordinary-bounds-unrelated.rs:18:74
+   |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+   |                                                                          ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
new file mode 100644
index 00000000000..db1641b0140
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs
@@ -0,0 +1,38 @@
+// edition:2018
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we get an error because none of our choices (either `'d` nor `'e`) are outlived
+// by both `'a` and `'b`.
+
+fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+//~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+where
+    'a: 'e,
+    'b: 'd,
+{
+    // Hidden type `Ordinary<'0>` with constraints:
+    //
+    // ```
+    // 'a: '0
+    // 'b: '0
+    // 'a in ['d, 'e]
+    // ```
+    if condition() { a } else { b }
+}
+
+fn condition() -> bool {
+    true
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
new file mode 100644
index 00000000000..cd2d46ac182
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -0,0 +1,21 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ordinary-bounds-unrelated.rs:18:74
+   |
+LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
+   |                                                                          ^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 23:1
+  --> $DIR/ordinary-bounds-unrelated.rs:23:1
+   |
+LL | / {
+LL | |     // Hidden type `Ordinary<'0>` with constraints:
+LL | |     //
+LL | |     // ```
+...  |
+LL | |     if condition() { a } else { b }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr
new file mode 100644
index 00000000000..af42ed1c5c1
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr
@@ -0,0 +1,9 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ordinary-bounds-unsuited.rs:20:62
+   |
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+   |                                                              ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
new file mode 100644
index 00000000000..7f9c92f15a2
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs
@@ -0,0 +1,41 @@
+// edition:2018
+
+#![feature(member_constraints)]
+
+trait Trait<'a, 'b> {}
+impl<T> Trait<'_, '_> for T {}
+
+// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types.
+//
+// I am purposefully avoiding the terms co- and contra-variant because
+// their application to regions depends on how you interpreted Rust
+// regions. -nikomatsakis
+struct Ordinary<'a>(&'a u8);
+
+// Here we need something outlived by `'a` *and* outlived by `'b`, but
+// we can only name `'a` and `'b` (and neither suits). So we get an
+// error. Somewhat unfortunate, though, since the caller would have to
+// consider the loans for both `'a` and `'b` alive.
+
+fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+    //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+{
+    // We return a value:
+    //
+    // ```
+    // 'a: '0
+    // 'b: '1
+    // '0 in ['a, 'b]
+    // ```
+    //
+    // but we don't have it.
+    //
+    // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
+    if condition() { a } else { b }
+}
+
+fn condition() -> bool {
+    true
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
new file mode 100644
index 00000000000..59ce93fa78b
--- /dev/null
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -0,0 +1,21 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/ordinary-bounds-unsuited.rs:20:62
+   |
+LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
+   |                                                              ^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 22:1
+  --> $DIR/ordinary-bounds-unsuited.rs:22:1
+   |
+LL | / {
+LL | |     // We return a value:
+LL | |     //
+LL | |     // ```
+...  |
+LL | |     if condition() { a } else { b }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.rs b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
index 2a5b365559e..52475f65a83 100644
--- a/src/test/ui/impl-trait/needs_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/needs_least_region_or_bound.rs
@@ -1,10 +1,24 @@
+// run-pass
+
+#![feature(member_constraints)]
+
 use std::fmt::Debug;
 
 trait MultiRegionTrait<'a, 'b> {}
 impl<'a, 'b> MultiRegionTrait<'a, 'b> for (&'a u32, &'b u32) {}
 
 fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
-//~^ ERROR ambiguous lifetime bound
+    // Here we have a constraint that:
+    //
+    // (x, y) has type (&'0 u32, &'1 u32)
+    //
+    // where
+    //
+    // 'a: '0
+    //
+    // then we require that `('0 u32, &'1 u32): MultiRegionTrait<'a,
+    // 'b>`, which winds up imposing a requirement that `'0 = 'a` and
+    // `'1 = 'b`.
     (x, y)
 }
 
diff --git a/src/test/ui/impl-trait/needs_least_region_or_bound.stderr b/src/test/ui/impl-trait/needs_least_region_or_bound.stderr
deleted file mode 100644
index f1b4d9c58f3..00000000000
--- a/src/test/ui/impl-trait/needs_least_region_or_bound.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: ambiguous lifetime bound in `impl Trait`
-  --> $DIR/needs_least_region_or_bound.rs:6:55
-   |
-LL | fn no_least_region<'a, 'b>(x: &'a u32, y: &'b u32) -> impl MultiRegionTrait<'a, 'b> {
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs
index 9c9397999ff..244293be726 100644
--- a/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-macro-item.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that `extern crate self;` is accepted
 // syntactically as an item for use in a macro.
diff --git a/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs b/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs
index 6f6343a6148..9cebb622eed 100644
--- a/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs
+++ b/src/test/ui/imports/extern-crate-self/extern-crate-self-pass.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 extern crate self as foo;
 
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs
index cf91a9714ad..30d87f90b30 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs
+++ b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 macro_rules! define_iso { () => {
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
index 6117e5f6f3c..cfae08fccaa 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
+++ b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:--cfg my_feature
 
 #![no_std]
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs
index bb4cf6ca99c..c87d58f63e2 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs
+++ b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:two_macros.rs
 
 extern crate two_macros;
diff --git a/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs
index c5adeaf17fa..9e69a27d7c4 100644
--- a/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs
+++ b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:two_macros.rs
 
 extern crate two_macros as core;
diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs
index 317441079ff..613ccc0b242 100644
--- a/src/test/ui/imports/gensymed.rs
+++ b/src/test/ui/imports/gensymed.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // aux-build:gensymed.rs
 
diff --git a/src/test/ui/imports/issue-53140.rs b/src/test/ui/imports/issue-53140.rs
index dbfba2c9433..1854ddf96b8 100644
--- a/src/test/ui/imports/issue-53140.rs
+++ b/src/test/ui/imports/issue-53140.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 mod m {
     pub struct S(u8);
diff --git a/src/test/ui/imports/issue-55811.rs b/src/test/ui/imports/issue-55811.rs
index 95316777fab..8cb602d868c 100644
--- a/src/test/ui/imports/issue-55811.rs
+++ b/src/test/ui/imports/issue-55811.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:issue-55811.rs
 
 extern crate issue_55811;
diff --git a/src/test/ui/imports/issue-56263.rs b/src/test/ui/imports/issue-56263.rs
index 4113d4390c3..4763ae4be99 100644
--- a/src/test/ui/imports/issue-56263.rs
+++ b/src/test/ui/imports/issue-56263.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 use ::std;
diff --git a/src/test/ui/imports/local-modularized-tricky-pass.rs b/src/test/ui/imports/local-modularized-tricky-pass.rs
index 59aac952b92..b52ddaf8954 100644
--- a/src/test/ui/imports/local-modularized-tricky-pass.rs
+++ b/src/test/ui/imports/local-modularized-tricky-pass.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 macro_rules! define_exported { () => {
     #[macro_export]
diff --git a/src/test/ui/imports/local-modularized.rs b/src/test/ui/imports/local-modularized.rs
index a073fe26eb6..8eeb1cf07bb 100644
--- a/src/test/ui/imports/local-modularized.rs
+++ b/src/test/ui/imports/local-modularized.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[macro_export(local_inner_macros)]
 macro_rules! dollar_crate_exported {
diff --git a/src/test/ui/inference/inference-variable-behind-raw-pointer.rs b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs
index 513b15ed088..a90b268db8c 100644
--- a/src/test/ui/inference/inference-variable-behind-raw-pointer.rs
+++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // tests that the following code compiles, but produces a future-compatibility warning
 
diff --git a/src/test/ui/issue-53912.rs b/src/test/ui/issue-53912.rs
index d2347c3077c..4718aea0429 100644
--- a/src/test/ui/issue-53912.rs
+++ b/src/test/ui/issue-53912.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
 // reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
diff --git a/src/test/ui/issues/issue-10396.rs b/src/test/ui/issues/issue-10396.rs
index d8e9aec8180..0781e5e3ed9 100644
--- a/src/test/ui/issues/issue-10396.rs
+++ b/src/test/ui/issues/issue-10396.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[derive(Debug)]
 enum Foo<'s> {
diff --git a/src/test/ui/issues/issue-10456.rs b/src/test/ui/issues/issue-10456.rs
index 4b548362f4a..7eac095de5d 100644
--- a/src/test/ui/issues/issue-10456.rs
+++ b/src/test/ui/issues/issue-10456.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 pub struct Foo;
diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs
index ceb44ecf7f5..111078abb37 100644
--- a/src/test/ui/issues/issue-10536.rs
+++ b/src/test/ui/issues/issue-10536.rs
@@ -11,13 +11,9 @@ macro_rules! foo{
 pub fn main() {
     foo!();
 
-    assert!({one! two()});
-    //~^ ERROR macros that expand to items
-    //~| ERROR cannot find macro `one!` in this scope
-    //~| ERROR mismatched types
+    assert!({one! two()}); //~ ERROR expected open delimiter
 
     // regardless of whether nested macro_rules works, the following should at
     // least throw a conventional error.
-    assert!({one! two});
-    //~^ ERROR expected `(` or `{`, found `}`
+    assert!({one! two}); //~ ERROR expected open delimiter
 }
diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr
index 584cdf43a8f..73f948107f1 100644
--- a/src/test/ui/issues/issue-10536.stderr
+++ b/src/test/ui/issues/issue-10536.stderr
@@ -1,38 +1,14 @@
-error: macros that expand to items must be delimited with braces or followed by a semicolon
-  --> $DIR/issue-10536.rs:14:22
+error: expected open delimiter
+  --> $DIR/issue-10536.rs:14:19
    |
 LL |     assert!({one! two()});
-   |                      ^^
-help: change the delimiters to curly braces
-   |
-LL |     assert!({one! two {}});
-   |                       ^^
-help: add a semicolon
-   |
-LL |     assert!({one! two();});
-   |                        ^
+   |                   ^^^ expected open delimiter
 
-error: expected `(` or `{`, found `}`
-  --> $DIR/issue-10536.rs:21:22
+error: expected open delimiter
+  --> $DIR/issue-10536.rs:18:19
    |
 LL |     assert!({one! two});
-   |                      ^ expected `(` or `{`
-
-error: cannot find macro `one!` in this scope
-  --> $DIR/issue-10536.rs:14:14
-   |
-LL |     assert!({one! two()});
-   |              ^^^
-
-error[E0308]: mismatched types
-  --> $DIR/issue-10536.rs:14:13
-   |
-LL |     assert!({one! two()});
-   |             ^^^^^^^^^^^^ expected bool, found ()
-   |
-   = note: expected type `bool`
-              found type `()`
+   |                   ^^^ expected open delimiter
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-10763.rs b/src/test/ui/issues/issue-10763.rs
index f2d4c5b47d7..091a7c52963 100644
--- a/src/test/ui/issues/issue-10763.rs
+++ b/src/test/ui/issues/issue-10763.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-10853.rs b/src/test/ui/issues/issue-10853.rs
index 0b74eaddcdd..c9de39feda6 100644
--- a/src/test/ui/issues/issue-10853.rs
+++ b/src/test/ui/issues/issue-10853.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![deny(missing_docs)]
diff --git a/src/test/ui/issues/issue-10902.rs b/src/test/ui/issues/issue-10902.rs
index 5e7f8ed7fd5..d53ce9a1db8 100644
--- a/src/test/ui/issues/issue-10902.rs
+++ b/src/test/ui/issues/issue-10902.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-11384.rs b/src/test/ui/issues/issue-11384.rs
index 59d85b175cf..443c2be08bb 100644
--- a/src/test/ui/issues/issue-11384.rs
+++ b/src/test/ui/issues/issue-11384.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Common { fn dummy(&self) { } }
diff --git a/src/test/ui/issues/issue-11592.rs b/src/test/ui/issues/issue-11592.rs
index e2028bd56f9..0298f83baf8 100644
--- a/src/test/ui/issues/issue-11592.rs
+++ b/src/test/ui/issues/issue-11592.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 //! Ensure the private trait Bar isn't complained about.
 
 #![deny(missing_docs)]
diff --git a/src/test/ui/issues/issue-11612.rs b/src/test/ui/issues/issue-11612.rs
index fd4fb2443cb..553648a5ebc 100644
--- a/src/test/ui/issues/issue-11612.rs
+++ b/src/test/ui/issues/issue-11612.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // #11612
 // We weren't updating the auto adjustments with all the resolved
diff --git a/src/test/ui/issues/issue-11869.rs b/src/test/ui/issues/issue-11869.rs
index e62879f1f29..a44094bfb23 100644
--- a/src/test/ui/issues/issue-11869.rs
+++ b/src/test/ui/issues/issue-11869.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-1251.rs b/src/test/ui/issues/issue-1251.rs
index 84a14a8c09b..63b5a4dd1b3 100644
--- a/src/test/ui/issues/issue-1251.rs
+++ b/src/test/ui/issues/issue-1251.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-12729.rs b/src/test/ui/issues/issue-12729.rs
index c2572c78280..67c1bdc32ed 100644
--- a/src/test/ui/issues/issue-12729.rs
+++ b/src/test/ui/issues/issue-12729.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-13105.rs b/src/test/ui/issues/issue-13105.rs
index 0e118043d55..2410e2f1367 100644
--- a/src/test/ui/issues/issue-13105.rs
+++ b/src/test/ui/issues/issue-13105.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Foo {
diff --git a/src/test/ui/issues/issue-13167.rs b/src/test/ui/issues/issue-13167.rs
index dcc25a446fa..e04faabb7e8 100644
--- a/src/test/ui/issues/issue-13167.rs
+++ b/src/test/ui/issues/issue-13167.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 use std::slice;
diff --git a/src/test/ui/issues/issue-13214.rs b/src/test/ui/issues/issue-13214.rs
index af2d95c5e42..0015169b117 100644
--- a/src/test/ui/issues/issue-13214.rs
+++ b/src/test/ui/issues/issue-13214.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // defining static with struct that contains enum
 // with &'static str variant used to cause ICE
diff --git a/src/test/ui/issues/issue-13405.rs b/src/test/ui/issues/issue-13405.rs
index 32965cb0c6d..fb48abe2648 100644
--- a/src/test/ui/issues/issue-13405.rs
+++ b/src/test/ui/issues/issue-13405.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-13703.rs b/src/test/ui/issues/issue-13703.rs
index 212fff7bcec..fe5458a7d7c 100644
--- a/src/test/ui/issues/issue-13703.rs
+++ b/src/test/ui/issues/issue-13703.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 pub struct Foo<'a, 'b: 'a> { foo: &'a &'b isize }
diff --git a/src/test/ui/issues/issue-13775.rs b/src/test/ui/issues/issue-13775.rs
index 39e42dc2c0d..0359bb581d5 100644
--- a/src/test/ui/issues/issue-13775.rs
+++ b/src/test/ui/issues/issue-13775.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Foo {
diff --git a/src/test/ui/issues/issue-13837.rs b/src/test/ui/issues/issue-13837.rs
index d475ce1d833..06790fbd324 100644
--- a/src/test/ui/issues/issue-13837.rs
+++ b/src/test/ui/issues/issue-13837.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-14082.rs b/src/test/ui/issues/issue-14082.rs
index 4849077c144..e5f1b492f27 100644
--- a/src/test/ui/issues/issue-14082.rs
+++ b/src/test/ui/issues/issue-14082.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![allow(unused_imports, dead_code)]
diff --git a/src/test/ui/issues/issue-14254.rs b/src/test/ui/issues/issue-14254.rs
index 3ad388dc2d7..8b04fa192ad 100644
--- a/src/test/ui/issues/issue-14254.rs
+++ b/src/test/ui/issues/issue-14254.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Foo: Sized {
diff --git a/src/test/ui/issues/issue-14330.rs b/src/test/ui/issues/issue-14330.rs
index d8f225eb07c..be31fa5eabc 100644
--- a/src/test/ui/issues/issue-14330.rs
+++ b/src/test/ui/issues/issue-14330.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_imports)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-14837.rs b/src/test/ui/issues/issue-14837.rs
index 54387804aff..a276e27f9dc 100644
--- a/src/test/ui/issues/issue-14837.rs
+++ b/src/test/ui/issues/issue-14837.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #[deny(dead_code)]
diff --git a/src/test/ui/issues/issue-14901.rs b/src/test/ui/issues/issue-14901.rs
index 9b89c1631df..c164658331e 100644
--- a/src/test/ui/issues/issue-14901.rs
+++ b/src/test/ui/issues/issue-14901.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Reader {}
 
 enum Wrapper<'a> {
diff --git a/src/test/ui/issues/issue-14933.rs b/src/test/ui/issues/issue-14933.rs
index 9249ba3d646..f229c0f7c26 100644
--- a/src/test/ui/issues/issue-14933.rs
+++ b/src/test/ui/issues/issue-14933.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 pub type BigRat<T = isize> = T;
diff --git a/src/test/ui/issues/issue-14936.rs b/src/test/ui/issues/issue-14936.rs
index bd3c99ad8d7..809a1088992 100644
--- a/src/test/ui/issues/issue-14936.rs
+++ b/src/test/ui/issues/issue-14936.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_macros)]
 #![allow(dead_code)]
 #![feature(asm)]
diff --git a/src/test/ui/issues/issue-14959.rs b/src/test/ui/issues/issue-14959.rs
index 60daaafbcc8..bd6c7a2bda9 100644
--- a/src/test/ui/issues/issue-14959.rs
+++ b/src/test/ui/issues/issue-14959.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![feature(fn_traits, unboxed_closures)]
diff --git a/src/test/ui/issues/issue-15108.rs b/src/test/ui/issues/issue-15108.rs
index d2b56c0949d..b8231ad4e83 100644
--- a/src/test/ui/issues/issue-15108.rs
+++ b/src/test/ui/issues/issue-15108.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-15261.rs b/src/test/ui/issues/issue-15261.rs
index 4119cb055c5..dd859475f9c 100644
--- a/src/test/ui/issues/issue-15261.rs
+++ b/src/test/ui/issues/issue-15261.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-15689-2.rs b/src/test/ui/issues/issue-15689-2.rs
index 4a132611391..1731a356ccd 100644
--- a/src/test/ui/issues/issue-15689-2.rs
+++ b/src/test/ui/issues/issue-15689-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-15735.rs b/src/test/ui/issues/issue-15735.rs
index 20634cc3881..0da4d4a620b 100644
--- a/src/test/ui/issues/issue-15735.rs
+++ b/src/test/ui/issues/issue-15735.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct A<'a> {
     a: &'a i32,
diff --git a/src/test/ui/issues/issue-16596.rs b/src/test/ui/issues/issue-16596.rs
index 3aa6c20ec57..693dea436bb 100644
--- a/src/test/ui/issues/issue-16596.rs
+++ b/src/test/ui/issues/issue-16596.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 trait MatrixRow { fn dummy(&self) { }}
diff --git a/src/test/ui/issues/issue-16668.rs b/src/test/ui/issues/issue-16668.rs
index b570a2ced67..a898ab20a48 100644
--- a/src/test/ui/issues/issue-16668.rs
+++ b/src/test/ui/issues/issue-16668.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct Parser<'a, I, O> {
     parse: Box<dyn FnMut(I) -> Result<O, String> + 'a>
diff --git a/src/test/ui/issues/issue-17121.rs b/src/test/ui/issues/issue-17121.rs
index 706350fc1e2..0f1d4f5410d 100644
--- a/src/test/ui/issues/issue-17121.rs
+++ b/src/test/ui/issues/issue-17121.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 // ignore-cloudabi no std::fs
diff --git a/src/test/ui/issues/issue-17263.rs b/src/test/ui/issues/issue-17263.rs
index dce30275ff3..f24acb7b304 100644
--- a/src/test/ui/issues/issue-17263.rs
+++ b/src/test/ui/issues/issue-17263.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(box_syntax)]
 
diff --git a/src/test/ui/issues/issue-17336.rs b/src/test/ui/issues/issue-17336.rs
index e2c0e8b91cc..830d799fb65 100644
--- a/src/test/ui/issues/issue-17336.rs
+++ b/src/test/ui/issues/issue-17336.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_must_use)]
 #[allow(dead_code)]
 fn check(a: &str) {
diff --git a/src/test/ui/issues/issue-17450.rs b/src/test/ui/issues/issue-17450.rs
index 70f33e3e661..595e0a4d25c 100644
--- a/src/test/ui/issues/issue-17450.rs
+++ b/src/test/ui/issues/issue-17450.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code, warnings)]
 
 static mut x: isize = 3;
diff --git a/src/test/ui/issues/issue-17718-const-destructors.rs b/src/test/ui/issues/issue-17718-const-destructors.rs
index 133420b688e..7ec025ec3af 100644
--- a/src/test/ui/issues/issue-17718-const-destructors.rs
+++ b/src/test/ui/issues/issue-17718-const-destructors.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct A;
 impl Drop for A {
diff --git a/src/test/ui/issues/issue-17732.rs b/src/test/ui/issues/issue-17732.rs
index 7993bbb38bb..17135c191ca 100644
--- a/src/test/ui/issues/issue-17732.rs
+++ b/src/test/ui/issues/issue-17732.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-17746.rs b/src/test/ui/issues/issue-17746.rs
index 45c5b858ecd..847b2eb60bb 100644
--- a/src/test/ui/issues/issue-17746.rs
+++ b/src/test/ui/issues/issue-17746.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #17746
 
diff --git a/src/test/ui/issues/issue-17904.rs b/src/test/ui/issues/issue-17904.rs
index 2fe54957b3c..d916abb9c73 100644
--- a/src/test/ui/issues/issue-17904.rs
+++ b/src/test/ui/issues/issue-17904.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Test that we can parse where clauses on various forms of tuple
 // structs.
diff --git a/src/test/ui/issues/issue-18083.rs b/src/test/ui/issues/issue-18083.rs
index c2cf2919ff0..f159ed4a0ce 100644
--- a/src/test/ui/issues/issue-18083.rs
+++ b/src/test/ui/issues/issue-18083.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_imports)]
 // These crossed imports should resolve fine, and not block on
diff --git a/src/test/ui/issues/issue-18088.rs b/src/test/ui/issues/issue-18088.rs
index 67000d9a6ec..06f259958f8 100644
--- a/src/test/ui/issues/issue-18088.rs
+++ b/src/test/ui/issues/issue-18088.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub trait Indexable<T>: std::ops::Index<usize, Output = T> {
     fn index2(&self, i: usize) -> &T {
diff --git a/src/test/ui/issues/issue-18188.rs b/src/test/ui/issues/issue-18188.rs
index 4d0c4464759..da10a8647ba 100644
--- a/src/test/ui/issues/issue-18188.rs
+++ b/src/test/ui/issues/issue-18188.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 pub trait Promisable: Send + Sync {}
diff --git a/src/test/ui/issues/issue-1821.rs b/src/test/ui/issues/issue-1821.rs
index 0177b70a698..db97a507b68 100644
--- a/src/test/ui/issues/issue-1821.rs
+++ b/src/test/ui/issues/issue-1821.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-18446-2.rs b/src/test/ui/issues/issue-18446-2.rs
index 3e04a914d45..6b984c13da5 100644
--- a/src/test/ui/issues/issue-18446-2.rs
+++ b/src/test/ui/issues/issue-18446-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Test that methods in trait impls should override default methods.
 
diff --git a/src/test/ui/issues/issue-1866.rs b/src/test/ui/issues/issue-1866.rs
index 3de547bfe6f..0223e2ebea9 100644
--- a/src/test/ui/issues/issue-1866.rs
+++ b/src/test/ui/issues/issue-1866.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-18738.rs b/src/test/ui/issues/issue-18738.rs
index c3bd022fa44..ec4429234bc 100644
--- a/src/test/ui/issues/issue-18738.rs
+++ b/src/test/ui/issues/issue-18738.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[derive(Eq, PartialEq, PartialOrd, Ord)]
 enum Test<'a> {
diff --git a/src/test/ui/issues/issue-18809.rs b/src/test/ui/issues/issue-18809.rs
index fb31666b22e..9b8275f8119 100644
--- a/src/test/ui/issues/issue-18809.rs
+++ b/src/test/ui/issues/issue-18809.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 trait Tup {
     type T0;
     type T1;
diff --git a/src/test/ui/issues/issue-18906.rs b/src/test/ui/issues/issue-18906.rs
index 0b9625b1868..387fd41fb7a 100644
--- a/src/test/ui/issues/issue-18906.rs
+++ b/src/test/ui/issues/issue-18906.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-18988.rs b/src/test/ui/issues/issue-18988.rs
index 7fe662e907d..6dbfd3a0a98 100644
--- a/src/test/ui/issues/issue-18988.rs
+++ b/src/test/ui/issues/issue-18988.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 pub trait Foo : Send { }
 
diff --git a/src/test/ui/issues/issue-19037.rs b/src/test/ui/issues/issue-19037.rs
index 4efc0719ffb..30497d3e94f 100644
--- a/src/test/ui/issues/issue-19037.rs
+++ b/src/test/ui/issues/issue-19037.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-19081.rs b/src/test/ui/issues/issue-19081.rs
index b487cdd5c75..0948cd3271b 100644
--- a/src/test/ui/issues/issue-19081.rs
+++ b/src/test/ui/issues/issue-19081.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Hasher {
     type State;
 
diff --git a/src/test/ui/issues/issue-19097.rs b/src/test/ui/issues/issue-19097.rs
index 8055e106251..c800e0bd12a 100644
--- a/src/test/ui/issues/issue-19097.rs
+++ b/src/test/ui/issues/issue-19097.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // regression test for #19097
 
diff --git a/src/test/ui/issues/issue-19098.rs b/src/test/ui/issues/issue-19098.rs
index 690fe944097..37c0d7f0522 100644
--- a/src/test/ui/issues/issue-19098.rs
+++ b/src/test/ui/issues/issue-19098.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Handler {
     fn handle(&self, _: &mut String);
 }
diff --git a/src/test/ui/issues/issue-19102.rs b/src/test/ui/issues/issue-19102.rs
index 962cd8d3f6f..76ed3efc4ed 100644
--- a/src/test/ui/issues/issue-19102.rs
+++ b/src/test/ui/issues/issue-19102.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_imports)]
 #![deny(unused_qualifications)]
 
diff --git a/src/test/ui/issues/issue-19129-1.rs b/src/test/ui/issues/issue-19129-1.rs
index 4be2cc6d179..e17ee053f33 100644
--- a/src/test/ui/issues/issue-19129-1.rs
+++ b/src/test/ui/issues/issue-19129-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Trait<Input> {
diff --git a/src/test/ui/issues/issue-19129-2.rs b/src/test/ui/issues/issue-19129-2.rs
index d11ef8af709..30c64573a15 100644
--- a/src/test/ui/issues/issue-19129-2.rs
+++ b/src/test/ui/issues/issue-19129-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_variables)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-19398.rs b/src/test/ui/issues/issue-19398.rs
index 5daa14b7cb7..28d266a1d61 100644
--- a/src/test/ui/issues/issue-19398.rs
+++ b/src/test/ui/issues/issue-19398.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait T {
diff --git a/src/test/ui/issues/issue-19404.rs b/src/test/ui/issues/issue-19404.rs
index 59544393bae..40c9fdac7b0 100644
--- a/src/test/ui/issues/issue-19404.rs
+++ b/src/test/ui/issues/issue-19404.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 use std::any::TypeId;
diff --git a/src/test/ui/issues/issue-19479.rs b/src/test/ui/issues/issue-19479.rs
index 8b78952a6e2..c134d85c7e9 100644
--- a/src/test/ui/issues/issue-19479.rs
+++ b/src/test/ui/issues/issue-19479.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Base {
diff --git a/src/test/ui/issues/issue-19631.rs b/src/test/ui/issues/issue-19631.rs
index 8c58331e581..015758dd6e1 100644
--- a/src/test/ui/issues/issue-19631.rs
+++ b/src/test/ui/issues/issue-19631.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-19632.rs b/src/test/ui/issues/issue-19632.rs
index b032b67c1eb..ddd87a9f6e9 100644
--- a/src/test/ui/issues/issue-19632.rs
+++ b/src/test/ui/issues/issue-19632.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-19850.rs b/src/test/ui/issues/issue-19850.rs
index fb64ef89405..d51cf0cfcb9 100644
--- a/src/test/ui/issues/issue-19850.rs
+++ b/src/test/ui/issues/issue-19850.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_variables)]
 // Test that `<Type as Trait>::Output` and `Self::Output` are accepted as type annotations in let
 // bindings
diff --git a/src/test/ui/issues/issue-19982.rs b/src/test/ui/issues/issue-19982.rs
index 6b5a4b2c10e..fb88781ee28 100644
--- a/src/test/ui/issues/issue-19982.rs
+++ b/src/test/ui/issues/issue-19982.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(fn_traits, unboxed_closures)]
 
diff --git a/src/test/ui/issues/issue-20009.rs b/src/test/ui/issues/issue-20009.rs
index 6228d044ad1..730f1a9a162 100644
--- a/src/test/ui/issues/issue-20009.rs
+++ b/src/test/ui/issues/issue-20009.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Check that associated types are `Sized`
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-20091.rs b/src/test/ui/issues/issue-20091.rs
index 4ea567d25ca..68e0f65ca23 100644
--- a/src/test/ui/issues/issue-20091.rs
+++ b/src/test/ui/issues/issue-20091.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(stable_features)]
 
 // ignore-cloudabi no processes
diff --git a/src/test/ui/issues/issue-20186.rs b/src/test/ui/issues/issue-20186.rs
index 98d856e172a..28cbde772c5 100644
--- a/src/test/ui/issues/issue-20186.rs
+++ b/src/test/ui/issues/issue-20186.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 struct Foo;
diff --git a/src/test/ui/issues/issue-20396.rs b/src/test/ui/issues/issue-20396.rs
index 0e69b7f3d1e..5e0411b2cd2 100644
--- a/src/test/ui/issues/issue-20396.rs
+++ b/src/test/ui/issues/issue-20396.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![allow(dead_code)]
diff --git a/src/test/ui/issues/issue-20414.rs b/src/test/ui/issues/issue-20414.rs
index 1653a9da004..5c6929d45d1 100644
--- a/src/test/ui/issues/issue-20414.rs
+++ b/src/test/ui/issues/issue-20414.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-20454.rs b/src/test/ui/issues/issue-20454.rs
index d4920c0c759..13ce1daf30a 100644
--- a/src/test/ui/issues/issue-20454.rs
+++ b/src/test/ui/issues/issue-20454.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_must_use)]
 use std::thread;
 
diff --git a/src/test/ui/issues/issue-2063-resource.rs b/src/test/ui/issues/issue-2063-resource.rs
index 6ed3e027ffa..ea4cbf2cede 100644
--- a/src/test/ui/issues/issue-2063-resource.rs
+++ b/src/test/ui/issues/issue-2063-resource.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // test that autoderef of a type like this does not
 // cause compiler to loop.  Note that no instances
diff --git a/src/test/ui/issues/issue-20644.rs b/src/test/ui/issues/issue-20644.rs
index db32344864c..bde65229ec2 100644
--- a/src/test/ui/issues/issue-20644.rs
+++ b/src/test/ui/issues/issue-20644.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_imports)]
 #![allow(stable_features)]
diff --git a/src/test/ui/issues/issue-20763-1.rs b/src/test/ui/issues/issue-20763-1.rs
index c5b28520945..0f0ac8f6462 100644
--- a/src/test/ui/issues/issue-20763-1.rs
+++ b/src/test/ui/issues/issue-20763-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-20763-2.rs b/src/test/ui/issues/issue-20763-2.rs
index cfa252b095e..e3b566d0503 100644
--- a/src/test/ui/issues/issue-20763-2.rs
+++ b/src/test/ui/issues/issue-20763-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-20797.rs b/src/test/ui/issues/issue-20797.rs
index e504b4705da..bda7e8f818b 100644
--- a/src/test/ui/issues/issue-20797.rs
+++ b/src/test/ui/issues/issue-20797.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // ignore-cloudabi no std::fs
 
 // Regression test for #20797.
diff --git a/src/test/ui/issues/issue-20825-2.rs b/src/test/ui/issues/issue-20825-2.rs
index cceed542186..7d72ef839ea 100644
--- a/src/test/ui/issues/issue-20825-2.rs
+++ b/src/test/ui/issues/issue-20825-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Subscriber {
     type Input;
 }
diff --git a/src/test/ui/issues/issue-21140.rs b/src/test/ui/issues/issue-21140.rs
index 86d4e63670f..92834bbb0e4 100644
--- a/src/test/ui/issues/issue-21140.rs
+++ b/src/test/ui/issues/issue-21140.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Trait where Self::Out: std::fmt::Display {
     type Out;
 }
diff --git a/src/test/ui/issues/issue-21174-2.rs b/src/test/ui/issues/issue-21174-2.rs
index 145b062baf6..351a98d5c85 100644
--- a/src/test/ui/issues/issue-21174-2.rs
+++ b/src/test/ui/issues/issue-21174-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 trait Trait<'a> {
diff --git a/src/test/ui/issues/issue-21245.rs b/src/test/ui/issues/issue-21245.rs
index edf482afc53..d0aa16bfb16 100644
--- a/src/test/ui/issues/issue-21245.rs
+++ b/src/test/ui/issues/issue-21245.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for issue #21245. Check that we are able to infer
 // the types in these examples correctly. It used to be that
diff --git a/src/test/ui/issues/issue-21363.rs b/src/test/ui/issues/issue-21363.rs
index 12efce9496e..d5f1eec061d 100644
--- a/src/test/ui/issues/issue-21363.rs
+++ b/src/test/ui/issues/issue-21363.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #![no_implicit_prelude]
diff --git a/src/test/ui/issues/issue-21402.rs b/src/test/ui/issues/issue-21402.rs
index 518d3cfe5a6..21e0d58b5f4 100644
--- a/src/test/ui/issues/issue-21402.rs
+++ b/src/test/ui/issues/issue-21402.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-21520.rs b/src/test/ui/issues/issue-21520.rs
index 450448f1a11..133bcc2360a 100644
--- a/src/test/ui/issues/issue-21520.rs
+++ b/src/test/ui/issues/issue-21520.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Test that the requirement (in `Bar`) that `T::Bar : 'static` does
 // not wind up propagating to `T`.
diff --git a/src/test/ui/issues/issue-21562.rs b/src/test/ui/issues/issue-21562.rs
index e31316d0709..2f3ee7b7490 100644
--- a/src/test/ui/issues/issue-21562.rs
+++ b/src/test/ui/issues/issue-21562.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-21622.rs b/src/test/ui/issues/issue-21622.rs
index 2b80f2f36c5..4aae089943f 100644
--- a/src/test/ui/issues/issue-21622.rs
+++ b/src/test/ui/issues/issue-21622.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/issues/issue-21634.rs b/src/test/ui/issues/issue-21634.rs
index 8941bb1c243..36b207bb2a4 100644
--- a/src/test/ui/issues/issue-21634.rs
+++ b/src/test/ui/issues/issue-21634.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(stable_features)]
 
 #![feature(cfg_target_feature)]
diff --git a/src/test/ui/issues/issue-21726.rs b/src/test/ui/issues/issue-21726.rs
index f2065976b35..1c8284c8295 100644
--- a/src/test/ui/issues/issue-21726.rs
+++ b/src/test/ui/issues/issue-21726.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #21726: an issue arose around the rules for
 // subtyping of projection types that resulted in an unconstrained
diff --git a/src/test/ui/issues/issue-21891.rs b/src/test/ui/issues/issue-21891.rs
index 9b1e44c1817..de0aa2919cf 100644
--- a/src/test/ui/issues/issue-21891.rs
+++ b/src/test/ui/issues/issue-21891.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-22066.rs b/src/test/ui/issues/issue-22066.rs
index 8c0b664d78a..fbf31aa4243 100644
--- a/src/test/ui/issues/issue-22066.rs
+++ b/src/test/ui/issues/issue-22066.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait LineFormatter<'a> {
     type Iter: Iterator<Item=&'a str> + 'a;
     fn iter(&'a self, line: &'a str) -> Self::Iter;
diff --git a/src/test/ui/issues/issue-22356.rs b/src/test/ui/issues/issue-22356.rs
index 3f3b1d3e5f1..ec4695e5e0a 100644
--- a/src/test/ui/issues/issue-22356.rs
+++ b/src/test/ui/issues/issue-22356.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(type_alias_bounds)]
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-22375.rs b/src/test/ui/issues/issue-22375.rs
index bae7b2bfab4..201aea3a05c 100644
--- a/src/test/ui/issues/issue-22375.rs
+++ b/src/test/ui/issues/issue-22375.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 trait A<T: A<T>> {}
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-22471.rs b/src/test/ui/issues/issue-22471.rs
index a22c7e6173e..befccc19bf8 100644
--- a/src/test/ui/issues/issue-22471.rs
+++ b/src/test/ui/issues/issue-22471.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(type_alias_bounds)]
 
diff --git a/src/test/ui/issues/issue-22777.rs b/src/test/ui/issues/issue-22777.rs
index f9b264623d6..81efb250dfa 100644
--- a/src/test/ui/issues/issue-22777.rs
+++ b/src/test/ui/issues/issue-22777.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // This test is reduced from libsyntax.  It is just checking that we
 // can successfully deal with a "deep" structure, which the drop-check
 // was hitting a recursion limit on at one point.
diff --git a/src/test/ui/issues/issue-22781.rs b/src/test/ui/issues/issue-22781.rs
index a7b94c106a4..37f40aa0421 100644
--- a/src/test/ui/issues/issue-22781.rs
+++ b/src/test/ui/issues/issue-22781.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_variables)]
 use std::collections::HashMap;
 use std::collections::hash_map::Entry::Vacant;
diff --git a/src/test/ui/issues/issue-22814.rs b/src/test/ui/issues/issue-22814.rs
index bcc7a8a5ae0..065e7edc67e 100644
--- a/src/test/ui/issues/issue-22814.rs
+++ b/src/test/ui/issues/issue-22814.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 trait Test {}
 
 macro_rules! test {
diff --git a/src/test/ui/issues/issue-22894.rs b/src/test/ui/issues/issue-22894.rs
index f5b26de54f5..7b1513a10c0 100644
--- a/src/test/ui/issues/issue-22894.rs
+++ b/src/test/ui/issues/issue-22894.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #[allow(dead_code)]
 static X: &'static str = &*"";
 fn main() {}
diff --git a/src/test/ui/issues/issue-2311-2.rs b/src/test/ui/issues/issue-2311-2.rs
index 40cda23186a..f735338fcdb 100644
--- a/src/test/ui/issues/issue-2311-2.rs
+++ b/src/test/ui/issues/issue-2311-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-2311.rs b/src/test/ui/issues/issue-2311.rs
index 07b9951e68d..151ad4e2664 100644
--- a/src/test/ui/issues/issue-2311.rs
+++ b/src/test/ui/issues/issue-2311.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(non_camel_case_types)]
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-2312.rs b/src/test/ui/issues/issue-2312.rs
index 1fc7b5a3f34..b445f9581b3 100644
--- a/src/test/ui/issues/issue-2312.rs
+++ b/src/test/ui/issues/issue-2312.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-23406.rs b/src/test/ui/issues/issue-23406.rs
index 9d77af0914f..2e57b16e3c7 100644
--- a/src/test/ui/issues/issue-23406.rs
+++ b/src/test/ui/issues/issue-23406.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait Inner {
     type T;
diff --git a/src/test/ui/issues/issue-23442.rs b/src/test/ui/issues/issue-23442.rs
index c3b613a06cd..659e1e07942 100644
--- a/src/test/ui/issues/issue-23442.rs
+++ b/src/test/ui/issues/issue-23442.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 use std::marker::PhantomData;
 
diff --git a/src/test/ui/issues/issue-23477.rs b/src/test/ui/issues/issue-23477.rs
index f363e6a0f47..b10b2e49616 100644
--- a/src/test/ui/issues/issue-23477.rs
+++ b/src/test/ui/issues/issue-23477.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compiler-flags: -g
 
 pub struct Dst {
diff --git a/src/test/ui/issues/issue-23550.rs b/src/test/ui/issues/issue-23550.rs
index 370d5c5aa3e..fad0ad7ecca 100644
--- a/src/test/ui/issues/issue-23550.rs
+++ b/src/test/ui/issues/issue-23550.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(core_intrinsics)]
 #![allow(warnings)]
 
diff --git a/src/test/ui/issues/issue-23649-3.rs b/src/test/ui/issues/issue-23649-3.rs
index 718fe606b80..febdc4256c7 100644
--- a/src/test/ui/issues/issue-23649-3.rs
+++ b/src/test/ui/issues/issue-23649-3.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #[derive(PartialEq)]
 struct Slice { slice: [u8] }
 
diff --git a/src/test/ui/issues/issue-24085.rs b/src/test/ui/issues/issue-24085.rs
index d06647762a9..dc2de922ff0 100644
--- a/src/test/ui/issues/issue-24085.rs
+++ b/src/test/ui/issues/issue-24085.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #24085. Errors were occurring in region
 // inference due to the requirement that `'a:b'`, which was getting
diff --git a/src/test/ui/issues/issue-24161.rs b/src/test/ui/issues/issue-24161.rs
index 99b09ba74d5..c5c8651d43b 100644
--- a/src/test/ui/issues/issue-24161.rs
+++ b/src/test/ui/issues/issue-24161.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[derive(Copy,Clone)]
 struct Functions {
diff --git a/src/test/ui/issues/issue-24227.rs b/src/test/ui/issues/issue-24227.rs
index 83e12caff6d..eaadaf7c449 100644
--- a/src/test/ui/issues/issue-24227.rs
+++ b/src/test/ui/issues/issue-24227.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // This resulted in an ICE. Test for future-proofing
 // Issue #24227
 
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/issues/issue-24338.rs
index fafeff06426..09cc99f9507 100644
--- a/src/test/ui/issues/issue-24338.rs
+++ b/src/test/ui/issues/issue-24338.rs
@@ -1,5 +1,5 @@
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait DictLike<'a> {
     type ItemsIterator: Iterator<Item=u8>;
diff --git a/src/test/ui/issues/issue-24389.rs b/src/test/ui/issues/issue-24389.rs
index da48a76e200..63d1687af50 100644
--- a/src/test/ui/issues/issue-24389.rs
+++ b/src/test/ui/issues/issue-24389.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 struct Foo;
diff --git a/src/test/ui/issues/issue-24434.rs b/src/test/ui/issues/issue-24434.rs
index 2424a1c92cd..b500b9d56dd 100644
--- a/src/test/ui/issues/issue-24434.rs
+++ b/src/test/ui/issues/issue-24434.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:--cfg set1
 
 #![cfg_attr(set1, feature(rustc_attrs))]
diff --git a/src/test/ui/issues/issue-2487-a.rs b/src/test/ui/issues/issue-2487-a.rs
index 36e121ddb7a..a43933d2020 100644
--- a/src/test/ui/issues/issue-2487-a.rs
+++ b/src/test/ui/issues/issue-2487-a.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-2502.rs b/src/test/ui/issues/issue-2502.rs
index 29b68c94c2e..9a2bbb82413 100644
--- a/src/test/ui/issues/issue-2502.rs
+++ b/src/test/ui/issues/issue-2502.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
diff --git a/src/test/ui/issues/issue-25180.rs b/src/test/ui/issues/issue-25180.rs
index 297f403c05e..12f8f88a170 100644
--- a/src/test/ui/issues/issue-25180.rs
+++ b/src/test/ui/issues/issue-25180.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-25394.rs b/src/test/ui/issues/issue-25394.rs
index d1638aa98a0..c41b554df14 100644
--- a/src/test/ui/issues/issue-25394.rs
+++ b/src/test/ui/issues/issue-25394.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[derive(Debug)]
 struct Row<T>([T]);
diff --git a/src/test/ui/issues/issue-25579.rs b/src/test/ui/issues/issue-25579.rs
index 31ba102746b..32b4b75b080 100644
--- a/src/test/ui/issues/issue-25579.rs
+++ b/src/test/ui/issues/issue-25579.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 enum Sexpression {
     Num(()),
diff --git a/src/test/ui/issues/issue-26095.rs b/src/test/ui/issues/issue-26095.rs
index 707cf1df512..1e3cc902e56 100644
--- a/src/test/ui/issues/issue-26095.rs
+++ b/src/test/ui/issues/issue-26095.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-2611-3.rs b/src/test/ui/issues/issue-2611-3.rs
index 5d4b65628de..7335d53f8a6 100644
--- a/src/test/ui/issues/issue-2611-3.rs
+++ b/src/test/ui/issues/issue-2611-3.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Tests that impls are allowed to have looser, more permissive bounds
 // than the traits require.
diff --git a/src/test/ui/issues/issue-26205.rs b/src/test/ui/issues/issue-26205.rs
index 01b71652c05..45ca998a831 100644
--- a/src/test/ui/issues/issue-26205.rs
+++ b/src/test/ui/issues/issue-26205.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 use std::ops::{Deref, DerefMut};
 
diff --git a/src/test/ui/issues/issue-26646.rs b/src/test/ui/issues/issue-26646.rs
index 6aa5e03996b..d6f51ce9c99 100644
--- a/src/test/ui/issues/issue-26646.rs
+++ b/src/test/ui/issues/issue-26646.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![deny(unused_attributes)]
 
 #[repr(C)]
diff --git a/src/test/ui/issues/issue-26997.rs b/src/test/ui/issues/issue-26997.rs
index dd48440720f..a2b32a13678 100644
--- a/src/test/ui/issues/issue-26997.rs
+++ b/src/test/ui/issues/issue-26997.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 pub struct Foo {
     x: isize,
diff --git a/src/test/ui/issues/issue-27105.rs b/src/test/ui/issues/issue-27105.rs
index 1aafa11768f..e7584d941ba 100644
--- a/src/test/ui/issues/issue-27105.rs
+++ b/src/test/ui/issues/issue-27105.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 use std::cell::RefCell;
 use std::rc::Rc;
 
diff --git a/src/test/ui/issues/issue-27281.rs b/src/test/ui/issues/issue-27281.rs
index 8403d9b4507..58b8f07bca6 100644
--- a/src/test/ui/issues/issue-27281.rs
+++ b/src/test/ui/issues/issue-27281.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Trait<'a> {
     type T;
     type U;
diff --git a/src/test/ui/issues/issue-2748-a.rs b/src/test/ui/issues/issue-2748-a.rs
index 683a931cc3d..5f566e186eb 100644
--- a/src/test/ui/issues/issue-2748-a.rs
+++ b/src/test/ui/issues/issue-2748-a.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_snake_case)]
 
diff --git a/src/test/ui/issues/issue-27583.rs b/src/test/ui/issues/issue-27583.rs
index 763e9ebe24b..9981f867bd0 100644
--- a/src/test/ui/issues/issue-27583.rs
+++ b/src/test/ui/issues/issue-27583.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Regression test for issue #27583. Unclear how useful this will be
 // going forward, since the issue in question was EXTREMELY sensitive
 // to compiler internals (like the precise numbering of nodes), but
diff --git a/src/test/ui/issues/issue-27889.rs b/src/test/ui/issues/issue-27889.rs
index 22de7c7cfa5..bb5a186b457 100644
--- a/src/test/ui/issues/issue-27889.rs
+++ b/src/test/ui/issues/issue-27889.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 // Test that a field can have the same name in different variants
diff --git a/src/test/ui/issues/issue-2804-2.rs b/src/test/ui/issues/issue-2804-2.rs
index d5157420617..68933fc2e8a 100644
--- a/src/test/ui/issues/issue-2804-2.rs
+++ b/src/test/ui/issues/issue-2804-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Minimized version of issue-2804.rs. Both check that callee IDs don't
 // clobber the previous node ID in a macro expr
diff --git a/src/test/ui/issues/issue-28279.rs b/src/test/ui/issues/issue-28279.rs
index fab91160a88..e36a9551ab5 100644
--- a/src/test/ui/issues/issue-28279.rs
+++ b/src/test/ui/issues/issue-28279.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 use std::rc::Rc;
 
diff --git a/src/test/ui/issues/issue-28561.rs b/src/test/ui/issues/issue-28561.rs
index 9dcce9991f7..cc4e63696e5 100644
--- a/src/test/ui/issues/issue-28561.rs
+++ b/src/test/ui/issues/issue-28561.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
 struct Array<T> {
     f00: [T; 00],
diff --git a/src/test/ui/issues/issue-28600.rs b/src/test/ui/issues/issue-28600.rs
index 44a85924e3d..05c4050b03a 100644
--- a/src/test/ui/issues/issue-28600.rs
+++ b/src/test/ui/issues/issue-28600.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // #28600 ICE: pub extern fn with parameter type &str inside struct impl
 
 struct Test;
diff --git a/src/test/ui/issues/issue-28822.rs b/src/test/ui/issues/issue-28822.rs
index 7381c348cd6..2c0c01aa827 100644
--- a/src/test/ui/issues/issue-28822.rs
+++ b/src/test/ui/issues/issue-28822.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-28871.rs b/src/test/ui/issues/issue-28871.rs
index b7e02b85878..43564dfcc46 100644
--- a/src/test/ui/issues/issue-28871.rs
+++ b/src/test/ui/issues/issue-28871.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Regression test for #28871. The problem is that rustc encountered
 // two ways to project, one from a where clause and one from the where
 // clauses on the trait definition. (In fact, in this case, the where
diff --git a/src/test/ui/issues/issue-28936.rs b/src/test/ui/issues/issue-28936.rs
index 5365adf3e80..9267491aafd 100644
--- a/src/test/ui/issues/issue-28936.rs
+++ b/src/test/ui/issues/issue-28936.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub type Session = i32;
 pub struct StreamParser<'a, T> {
     _tokens: T,
diff --git a/src/test/ui/issues/issue-28999.rs b/src/test/ui/issues/issue-28999.rs
index 4f6fa412e8b..888a8010a2f 100644
--- a/src/test/ui/issues/issue-28999.rs
+++ b/src/test/ui/issues/issue-28999.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub struct Xyz<'a, V> {
     pub v: (V, &'a u32),
 }
diff --git a/src/test/ui/issues/issue-29030.rs b/src/test/ui/issues/issue-29030.rs
index 9ac7742e4f8..f9e89840314 100644
--- a/src/test/ui/issues/issue-29030.rs
+++ b/src/test/ui/issues/issue-29030.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[derive(Debug)]
 struct Message<'a, P: 'a = &'a [u8]> {
diff --git a/src/test/ui/issues/issue-29037.rs b/src/test/ui/issues/issue-29037.rs
index e0eb71f5de6..b1ca76be10d 100644
--- a/src/test/ui/issues/issue-29037.rs
+++ b/src/test/ui/issues/issue-29037.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // This test ensures that each pointer type `P<X>` is covariant in `X`.
 
diff --git a/src/test/ui/issues/issue-2904.rs b/src/test/ui/issues/issue-2904.rs
index 42f71a1b096..36bc8002f99 100644
--- a/src/test/ui/issues/issue-2904.rs
+++ b/src/test/ui/issues/issue-2904.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_must_use)]
 #![allow(dead_code)]
 #![allow(unused_mut)]
diff --git a/src/test/ui/issues/issue-29048.rs b/src/test/ui/issues/issue-29048.rs
index 6c4b6183c37..e3ccb0d6579 100644
--- a/src/test/ui/issues/issue-29048.rs
+++ b/src/test/ui/issues/issue-29048.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub struct Chan;
 pub struct ChanSelect<'c, T> {
     chans: Vec<(&'c Chan, T)>,
diff --git a/src/test/ui/issues/issue-29071.rs b/src/test/ui/issues/issue-29071.rs
index 1ea4a54226c..7e016a715cd 100644
--- a/src/test/ui/issues/issue-29071.rs
+++ b/src/test/ui/issues/issue-29071.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-29276.rs b/src/test/ui/issues/issue-29276.rs
index 2a0358bc52a..2532dac9772 100644
--- a/src/test/ui/issues/issue-29276.rs
+++ b/src/test/ui/issues/issue-29276.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct S([u8; { struct Z; 0 }]);
 
diff --git a/src/test/ui/issues/issue-29516.rs b/src/test/ui/issues/issue-29516.rs
index 8082694e15c..8966730fd87 100644
--- a/src/test/ui/issues/issue-29516.rs
+++ b/src/test/ui/issues/issue-29516.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(optin_builtin_traits)]
 
 auto trait NotSame {}
diff --git a/src/test/ui/issues/issue-29540.rs b/src/test/ui/issues/issue-29540.rs
index b68205eda86..e472f71aa7f 100644
--- a/src/test/ui/issues/issue-29540.rs
+++ b/src/test/ui/issues/issue-29540.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #[derive(Debug)]
 pub struct Config {
     pub name: String,
diff --git a/src/test/ui/issues/issue-29710.rs b/src/test/ui/issues/issue-29710.rs
index 58907e78e48..d4de756e56f 100644
--- a/src/test/ui/issues/issue-29710.rs
+++ b/src/test/ui/issues/issue-29710.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![deny(unused_results)]
 #![allow(dead_code)]
 
diff --git a/src/test/ui/issues/issue-29740.rs b/src/test/ui/issues/issue-29740.rs
index f37d868ab7e..50a03d86acb 100644
--- a/src/test/ui/issues/issue-29740.rs
+++ b/src/test/ui/issues/issue-29740.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #29740. Inefficient MIR matching algorithms
 // generated way too much code for this sort of case, leading to OOM.
diff --git a/src/test/ui/issues/issue-29743.rs b/src/test/ui/issues/issue-29743.rs
index 5bc3b0c537a..2598b07490e 100644
--- a/src/test/ui/issues/issue-29743.rs
+++ b/src/test/ui/issues/issue-29743.rs
@@ -1,5 +1,5 @@
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let mut i = [1, 2, 3];
diff --git a/src/test/ui/issues/issue-31260.rs b/src/test/ui/issues/issue-31260.rs
index f7e717c59ac..608900301e0 100644
--- a/src/test/ui/issues/issue-31260.rs
+++ b/src/test/ui/issues/issue-31260.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 pub struct Struct<K: 'static> {
     pub field: K,
diff --git a/src/test/ui/issues/issue-3149.rs b/src/test/ui/issues/issue-3149.rs
index c9a6f537757..da3fe9ad6ec 100644
--- a/src/test/ui/issues/issue-3149.rs
+++ b/src/test/ui/issues/issue-3149.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_snake_case)]
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-31597.rs b/src/test/ui/issues/issue-31597.rs
index 3962f13fe9b..1d28a91ea7e 100644
--- a/src/test/ui/issues/issue-31597.rs
+++ b/src/test/ui/issues/issue-31597.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait Make {
     type Out;
diff --git a/src/test/ui/issues/issue-32324.rs b/src/test/ui/issues/issue-32324.rs
index 9abbe321604..eaad98d6785 100644
--- a/src/test/ui/issues/issue-32324.rs
+++ b/src/test/ui/issues/issue-32324.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 trait Resources {
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.rs b/src/test/ui/issues/issue-33140-traitobject-crate.rs
index 078f3f3dd2c..03567b20a8f 100644
--- a/src/test/ui/issues/issue-33140-traitobject-crate.rs
+++ b/src/test/ui/issues/issue-33140-traitobject-crate.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(order_dependent_trait_objects)]
 
diff --git a/src/test/ui/issues/issue-33264.rs b/src/test/ui/issues/issue-33264.rs
index 51608b48be2..e6370bc84de 100644
--- a/src/test/ui/issues/issue-33264.rs
+++ b/src/test/ui/issues/issue-33264.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // only-x86_64
 
 #![allow(dead_code, non_upper_case_globals)]
diff --git a/src/test/ui/issues/issue-33287.rs b/src/test/ui/issues/issue-33287.rs
index cc47e58fcdc..036a1e37688 100644
--- a/src/test/ui/issues/issue-33287.rs
+++ b/src/test/ui/issues/issue-33287.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 const A: [u32; 1] = [0];
diff --git a/src/test/ui/issues/issue-33903.rs b/src/test/ui/issues/issue-33903.rs
index 4fdc8dda8b4..6a8305dabeb 100644
--- a/src/test/ui/issues/issue-33903.rs
+++ b/src/test/ui/issues/issue-33903.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Issue 33903:
 // Built-in indexing should be used even when the index is not
diff --git a/src/test/ui/issues/issue-34194.rs b/src/test/ui/issues/issue-34194.rs
index b65de91d69b..ea89e4cbdeb 100644
--- a/src/test/ui/issues/issue-34194.rs
+++ b/src/test/ui/issues/issue-34194.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 struct A {
diff --git a/src/test/ui/issues/issue-3424.rs b/src/test/ui/issues/issue-3424.rs
index 19f9f13e144..a8ff03e2a24 100644
--- a/src/test/ui/issues/issue-3424.rs
+++ b/src/test/ui/issues/issue-3424.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 // rustc --test ignores2.rs && ./ignores2
diff --git a/src/test/ui/issues/issue-34751.rs b/src/test/ui/issues/issue-34751.rs
index cca06c573e0..a921cb50612 100644
--- a/src/test/ui/issues/issue-34751.rs
+++ b/src/test/ui/issues/issue-34751.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // #34751 ICE: 'rustc' panicked at 'assertion failed: !substs.has_regions_escaping_depth(0)'
 
diff --git a/src/test/ui/issues/issue-34780.rs b/src/test/ui/issues/issue-34780.rs
index bfe444e5d3f..3202ef64021 100644
--- a/src/test/ui/issues/issue-34780.rs
+++ b/src/test/ui/issues/issue-34780.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(stable_features)]
 #![feature(associated_consts)]
 
diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs
index 2a80c9f05d8..b415d655405 100644
--- a/src/test/ui/issues/issue-35376.rs
+++ b/src/test/ui/issues/issue-35376.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(specialization)]
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-35546.rs b/src/test/ui/issues/issue-35546.rs
index 500ba48e0b7..e2f0f98d57b 100644
--- a/src/test/ui/issues/issue-35546.rs
+++ b/src/test/ui/issues/issue-35546.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #35546. Check that we are able to codegen
 // this. Before we had problems because of the drop glue signature
diff --git a/src/test/ui/issues/issue-3563-2.rs b/src/test/ui/issues/issue-3563-2.rs
index 48f7c845d5e..5ab668eed18 100644
--- a/src/test/ui/issues/issue-3563-2.rs
+++ b/src/test/ui/issues/issue-3563-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait Canvas {
diff --git a/src/test/ui/issues/issue-36075.rs b/src/test/ui/issues/issue-36075.rs
index c9ca2f71341..00c8cf1fb8a 100644
--- a/src/test/ui/issues/issue-36075.rs
+++ b/src/test/ui/issues/issue-36075.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait DeclarationParser {
     type Declaration;
diff --git a/src/test/ui/issues/issue-3609.rs b/src/test/ui/issues/issue-3609.rs
index 9bccb2a21e3..e8fc073a158 100644
--- a/src/test/ui/issues/issue-3609.rs
+++ b/src/test/ui/issues/issue-3609.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_must_use)]
 #![allow(dead_code)]
 #![allow(unused_mut)]
diff --git a/src/test/ui/issues/issue-36744-without-calls.rs b/src/test/ui/issues/issue-36744-without-calls.rs
index 57d63e67f3c..4d03d9bbca6 100644
--- a/src/test/ui/issues/issue-36744-without-calls.rs
+++ b/src/test/ui/issues/issue-36744-without-calls.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Tests for an LLVM abort when storing a lifetime-parametric fn into
 // context that is expecting one that is not lifetime-parametric
 // (i.e., has no `for <'_>`).
diff --git a/src/test/ui/issues/issue-37323.rs b/src/test/ui/issues/issue-37323.rs
index a7cf0cd1bd5..61c8029adf5 100644
--- a/src/test/ui/issues/issue-37323.rs
+++ b/src/test/ui/issues/issue-37323.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(warnings)]
diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs
index 209f797b15c..1bec3d340d6 100644
--- a/src/test/ui/issues/issue-37598.rs
+++ b/src/test/ui/issues/issue-37598.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![feature(slice_patterns)]
 
diff --git a/src/test/ui/issues/issue-37655.rs b/src/test/ui/issues/issue-37655.rs
index bfc6406b921..fecff4e0246 100644
--- a/src/test/ui/issues/issue-37655.rs
+++ b/src/test/ui/issues/issue-37655.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Regression test for #37655. The problem was a false edge created by
 // coercion that wound up requiring that `'a` (in `split()`) outlive
 // `'b`, which shouldn't be necessary.
diff --git a/src/test/ui/issues/issue-37725.rs b/src/test/ui/issues/issue-37725.rs
index a572781f092..eefdc72f0c3 100644
--- a/src/test/ui/issues/issue-37725.rs
+++ b/src/test/ui/issues/issue-37725.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait Foo {
     fn foo(&self);
diff --git a/src/test/ui/issues/issue-37733.rs b/src/test/ui/issues/issue-37733.rs
index 2dcb0cd8cee..c1df28331a5 100644
--- a/src/test/ui/issues/issue-37733.rs
+++ b/src/test/ui/issues/issue-37733.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 type A = for<> fn();
 
diff --git a/src/test/ui/issues/issue-38727.rs b/src/test/ui/issues/issue-38727.rs
index d9f32637a90..3c728e9def1 100644
--- a/src/test/ui/issues/issue-38727.rs
+++ b/src/test/ui/issues/issue-38727.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #[repr(u64)]
 enum A {
diff --git a/src/test/ui/issues/issue-3874.rs b/src/test/ui/issues/issue-3874.rs
index 8a7eaf29539..b290da52080 100644
--- a/src/test/ui/issues/issue-3874.rs
+++ b/src/test/ui/issues/issue-3874.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-38875/issue-38875.rs b/src/test/ui/issues/issue-38875/issue-38875.rs
index df321b8dcbb..68981eaf2b5 100644
--- a/src/test/ui/issues/issue-38875/issue-38875.rs
+++ b/src/test/ui/issues/issue-38875/issue-38875.rs
@@ -1,5 +1,5 @@
 // aux-build:issue-38875-b.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 extern crate issue_38875_b;
 
diff --git a/src/test/ui/issues/issue-3888-2.rs b/src/test/ui/issues/issue-3888-2.rs
index 27d05b470be..3d4b184ab6b 100644
--- a/src/test/ui/issues/issue-3888-2.rs
+++ b/src/test/ui/issues/issue-3888-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-39089.rs b/src/test/ui/issues/issue-39089.rs
index 77be9d2c76b..12ca9e1da0f 100644
--- a/src/test/ui/issues/issue-39089.rs
+++ b/src/test/ui/issues/issue-39089.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 fn f<T: ?for<'a> Sized>() {}
 
diff --git a/src/test/ui/issues/issue-39467.rs b/src/test/ui/issues/issue-39467.rs
index 077e5cefd52..86e67560008 100644
--- a/src/test/ui/issues/issue-39467.rs
+++ b/src/test/ui/issues/issue-39467.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 macro_rules! expr { () => { () } }
 
diff --git a/src/test/ui/issues/issue-3979-2.rs b/src/test/ui/issues/issue-3979-2.rs
index eec8c85f276..f3fcfd2c8fb 100644
--- a/src/test/ui/issues/issue-3979-2.rs
+++ b/src/test/ui/issues/issue-3979-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 trait A {
diff --git a/src/test/ui/issues/issue-3991.rs b/src/test/ui/issues/issue-3991.rs
index bc63aae0b9e..b8ff671bf38 100644
--- a/src/test/ui/issues/issue-3991.rs
+++ b/src/test/ui/issues/issue-3991.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-39984.rs b/src/test/ui/issues/issue-39984.rs
index 5018b1c62c7..613aad1a34f 100644
--- a/src/test/ui/issues/issue-39984.rs
+++ b/src/test/ui/issues/issue-39984.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unreachable_code)]
 // Regression test for issue #39984.
diff --git a/src/test/ui/issues/issue-40136.rs b/src/test/ui/issues/issue-40136.rs
index 0849f54374b..412ddafdd97 100644
--- a/src/test/ui/issues/issue-40136.rs
+++ b/src/test/ui/issues/issue-40136.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 macro_rules! m { () => { 0 } }
diff --git a/src/test/ui/issues/issue-4025.rs b/src/test/ui/issues/issue-4025.rs
index fc036f3edd8..6e009ba6eb4 100644
--- a/src/test/ui/issues/issue-4025.rs
+++ b/src/test/ui/issues/issue-4025.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_mut)]
 /*
diff --git a/src/test/ui/issues/issue-40510-2.rs b/src/test/ui/issues/issue-40510-2.rs
index 2304badd17d..499fa8a04f2 100644
--- a/src/test/ui/issues/issue-40510-2.rs
+++ b/src/test/ui/issues/issue-40510-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 fn f() {
diff --git a/src/test/ui/issues/issue-40510-4.rs b/src/test/ui/issues/issue-40510-4.rs
index 45cd4fd94ef..5fad7e4a629 100644
--- a/src/test/ui/issues/issue-40510-4.rs
+++ b/src/test/ui/issues/issue-40510-4.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 fn f() {
diff --git a/src/test/ui/issues/issue-40962.rs b/src/test/ui/issues/issue-40962.rs
index 50d9276e79a..c051133cbed 100644
--- a/src/test/ui/issues/issue-40962.rs
+++ b/src/test/ui/issues/issue-40962.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 macro_rules! m {
     ($i:meta) => {
         #[derive($i)]
diff --git a/src/test/ui/issues/issue-41272.rs b/src/test/ui/issues/issue-41272.rs
index 4a43e11f47f..9cd20036286 100644
--- a/src/test/ui/issues/issue-41272.rs
+++ b/src/test/ui/issues/issue-41272.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct Foo;
 
diff --git a/src/test/ui/issues/issue-41298.rs b/src/test/ui/issues/issue-41298.rs
index e8eeabaf3a9..c719664de0d 100644
--- a/src/test/ui/issues/issue-41298.rs
+++ b/src/test/ui/issues/issue-41298.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct Function<T, F> { t: T, f: F }
 
diff --git a/src/test/ui/issues/issue-41628.rs b/src/test/ui/issues/issue-41628.rs
index b837a1e2346..92369fdcd49 100644
--- a/src/test/ui/issues/issue-41628.rs
+++ b/src/test/ui/issues/issue-41628.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![deny(dead_code)]
 
 #[used]
diff --git a/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs b/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs
index 4dddc484d33..6c6cec25a9a 100644
--- a/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs
+++ b/src/test/ui/issues/issue-41936-variance-coerce-unsized-cycle.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for #41936. The coerce-unsized trait check in
 // coherence was using subtyping, which triggered variance
diff --git a/src/test/ui/issues/issue-41998.rs b/src/test/ui/issues/issue-41998.rs
index e54bc201c1d..2f2842598fc 100644
--- a/src/test/ui/issues/issue-41998.rs
+++ b/src/test/ui/issues/issue-41998.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 
 fn main() {
diff --git a/src/test/ui/issues/issue-42467.rs b/src/test/ui/issues/issue-42467.rs
index 9ad515bdf5a..f1a55169ffd 100644
--- a/src/test/ui/issues/issue-42467.rs
+++ b/src/test/ui/issues/issue-42467.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 struct Foo<T>(T);
 
diff --git a/src/test/ui/issues/issue-42956.rs b/src/test/ui/issues/issue-42956.rs
index 34cb04657eb..8cf0ae00306 100644
--- a/src/test/ui/issues/issue-42956.rs
+++ b/src/test/ui/issues/issue-42956.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(stable_features)]
 #![feature(associated_consts)]
diff --git a/src/test/ui/issues/issue-43057.rs b/src/test/ui/issues/issue-43057.rs
index 3ed64bba904..7e1d5036f37 100644
--- a/src/test/ui/issues/issue-43057.rs
+++ b/src/test/ui/issues/issue-43057.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 macro_rules! column {
diff --git a/src/test/ui/issues/issue-43357.rs b/src/test/ui/issues/issue-43357.rs
index 6b8e7de8509..3090e229b6d 100644
--- a/src/test/ui/issues/issue-43357.rs
+++ b/src/test/ui/issues/issue-43357.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait Trait {
     type Output;
diff --git a/src/test/ui/issues/issue-43483.rs b/src/test/ui/issues/issue-43483.rs
index a123ae48496..f071d110f32 100644
--- a/src/test/ui/issues/issue-43483.rs
+++ b/src/test/ui/issues/issue-43483.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 trait VecN {
diff --git a/src/test/ui/issues/issue-44005.rs b/src/test/ui/issues/issue-44005.rs
index f6d1b7073a2..f6fe9fcbd89 100644
--- a/src/test/ui/issues/issue-44005.rs
+++ b/src/test/ui/issues/issue-44005.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 pub trait Foo<'a> {
     type Bar;
     fn foo(&'a self) -> Self::Bar;
diff --git a/src/test/ui/issues/issue-44056.rs b/src/test/ui/issues/issue-44056.rs
index 8ed371485c2..42f30bf3023 100644
--- a/src/test/ui/issues/issue-44056.rs
+++ b/src/test/ui/issues/issue-44056.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // only-x86_64
 // no-prefer-dynamic
 // compile-flags: -Ctarget-feature=+avx -Clto
diff --git a/src/test/ui/issues/issue-44247.rs b/src/test/ui/issues/issue-44247.rs
index b45d541f212..ef244e03857 100644
--- a/src/test/ui/issues/issue-44247.rs
+++ b/src/test/ui/issues/issue-44247.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 trait T {
     type X;
diff --git a/src/test/ui/issues/issue-44373-2.rs b/src/test/ui/issues/issue-44373-2.rs
index 18b2ce85125..7fdc4b1ee5b 100644
--- a/src/test/ui/issues/issue-44373-2.rs
+++ b/src/test/ui/issues/issue-44373-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 struct Foo(bool);
diff --git a/src/test/ui/issues/issue-44402.rs b/src/test/ui/issues/issue-44402.rs
index 7a2eaac1fd2..29b7eb5ee49 100644
--- a/src/test/ui/issues/issue-44402.rs
+++ b/src/test/ui/issues/issue-44402.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
diff --git a/src/test/ui/issues/issue-4464.rs b/src/test/ui/issues/issue-4464.rs
index c20c1cad669..13df6112482 100644
--- a/src/test/ui/issues/issue-4464.rs
+++ b/src/test/ui/issues/issue-4464.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-44730.rs b/src/test/ui/issues/issue-44730.rs
index 7dae6c8123b..93f0445d343 100644
--- a/src/test/ui/issues/issue-44730.rs
+++ b/src/test/ui/issues/issue-44730.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 //! dox
 
 #![deny(missing_docs)]
diff --git a/src/test/ui/issues/issue-44851.rs b/src/test/ui/issues/issue-44851.rs
index 697b4dcf427..735678047a5 100644
--- a/src/test/ui/issues/issue-44851.rs
+++ b/src/test/ui/issues/issue-44851.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 macro_rules! a {
     () => { "a" }
 }
diff --git a/src/test/ui/issues/issue-45425.rs b/src/test/ui/issues/issue-45425.rs
index a2ef85a2a02..99e018ba6c8 100644
--- a/src/test/ui/issues/issue-45425.rs
+++ b/src/test/ui/issues/issue-45425.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 use std::ops::Add;
 
diff --git a/src/test/ui/issues/issue-46959.rs b/src/test/ui/issues/issue-46959.rs
index e1147ac99ac..86f1158c198 100644
--- a/src/test/ui/issues/issue-46959.rs
+++ b/src/test/ui/issues/issue-46959.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![deny(non_camel_case_types)]
 
 #[allow(dead_code)]
diff --git a/src/test/ui/issues/issue-46964.rs b/src/test/ui/issues/issue-46964.rs
index 4688c9b0a1f..9cf53973d87 100644
--- a/src/test/ui/issues/issue-46964.rs
+++ b/src/test/ui/issues/issue-46964.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 mod my_mod {
     #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
     pub struct Name<'a> {
diff --git a/src/test/ui/issues/issue-47094.rs b/src/test/ui/issues/issue-47094.rs
index 6c78a3ba964..f17d4f88d90 100644
--- a/src/test/ui/issues/issue-47094.rs
+++ b/src/test/ui/issues/issue-47094.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[repr(C,u8)]
 enum Foo {
diff --git a/src/test/ui/issues/issue-47309.rs b/src/test/ui/issues/issue-47309.rs
index a9aeecb61b6..03092022d4d 100644
--- a/src/test/ui/issues/issue-47309.rs
+++ b/src/test/ui/issues/issue-47309.rs
@@ -3,7 +3,7 @@
 // See https://github.com/rust-lang/rust/issues/47309
 
 // compile-flags:-Clink-dead-code
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type="rlib"]
 
diff --git a/src/test/ui/issues/issue-47673.rs b/src/test/ui/issues/issue-47673.rs
index 6d7b8f9cc1b..0d813e2fad2 100644
--- a/src/test/ui/issues/issue-47673.rs
+++ b/src/test/ui/issues/issue-47673.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused_imports)]
 
 use {{}, {}};
diff --git a/src/test/ui/issues/issue-47703-1.rs b/src/test/ui/issues/issue-47703-1.rs
index 74323317f19..95738828647 100644
--- a/src/test/ui/issues/issue-47703-1.rs
+++ b/src/test/ui/issues/issue-47703-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct AtomicRefMut<'a> {
     value: &'a mut i32,
diff --git a/src/test/ui/issues/issue-47703-tuple.rs b/src/test/ui/issues/issue-47703-tuple.rs
index 377eeb67ae1..1b285f219dc 100644
--- a/src/test/ui/issues/issue-47703-tuple.rs
+++ b/src/test/ui/issues/issue-47703-tuple.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct WithDrop;
 
diff --git a/src/test/ui/issues/issue-47703.rs b/src/test/ui/issues/issue-47703.rs
index 22f2a1f364d..dbf49c7621f 100644
--- a/src/test/ui/issues/issue-47703.rs
+++ b/src/test/ui/issues/issue-47703.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct MyStruct<'a> {
     field: &'a mut (),
diff --git a/src/test/ui/issues/issue-47722.rs b/src/test/ui/issues/issue-47722.rs
index cefc872668c..b3c344257b6 100644
--- a/src/test/ui/issues/issue-47722.rs
+++ b/src/test/ui/issues/issue-47722.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Tests that automatic coercions from &mut T to *mut T
 // allow borrows of T to expire immediately - essentially, that
diff --git a/src/test/ui/issues/issue-47789.rs b/src/test/ui/issues/issue-47789.rs
index 334bd608add..28671db0998 100644
--- a/src/test/ui/issues/issue-47789.rs
+++ b/src/test/ui/issues/issue-47789.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(non_upper_case_globals)]
 
 static mut x: &'static u32 = &0;
diff --git a/src/test/ui/issues/issue-4830.rs b/src/test/ui/issues/issue-4830.rs
index cf94094a798..3724bb6393c 100644
--- a/src/test/ui/issues/issue-4830.rs
+++ b/src/test/ui/issues/issue-4830.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/issues/issue-48551.rs b/src/test/ui/issues/issue-48551.rs
index b5dd673b047..903b2e29929 100644
--- a/src/test/ui/issues/issue-48551.rs
+++ b/src/test/ui/issues/issue-48551.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Regression test for #48551. Covers a case where duplicate candidates
 // arose during associated type projection.
 
diff --git a/src/test/ui/issues/issue-49556.rs b/src/test/ui/issues/issue-49556.rs
index 46d9e749aae..d3c6d17f416 100644
--- a/src/test/ui/issues/issue-49556.rs
+++ b/src/test/ui/issues/issue-49556.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 fn iter<'a>(data: &'a [usize]) -> impl Iterator<Item = usize> + 'a {
     data.iter()
         .map(
diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs
index dd7b9eeb8d5..79cc107d4fe 100644
--- a/src/test/ui/issues/issue-49579.rs
+++ b/src/test/ui/issues/issue-49579.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // ignore-emscripten no i128 support
 
 fn fibs(n: u32) -> impl Iterator<Item=u128> {
diff --git a/src/test/ui/issues/issue-49934.rs b/src/test/ui/issues/issue-49934.rs
index ad410f30c04..e75381afae9 100644
--- a/src/test/ui/issues/issue-49934.rs
+++ b/src/test/ui/issues/issue-49934.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(stmt_expr_attributes)]
 #![warn(unused_attributes)] //~ NOTE lint level defined here
diff --git a/src/test/ui/issues/issue-50187.rs b/src/test/ui/issues/issue-50187.rs
index cda1c4d5faa..f530c3853e3 100644
--- a/src/test/ui/issues/issue-50187.rs
+++ b/src/test/ui/issues/issue-50187.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(decl_macro)]
 
diff --git a/src/test/ui/issues/issue-50411.rs b/src/test/ui/issues/issue-50411.rs
index 1ba47d3b932..a32faa69841 100644
--- a/src/test/ui/issues/issue-50411.rs
+++ b/src/test/ui/issues/issue-50411.rs
@@ -4,7 +4,7 @@
 // second time. Uncool.
 
 // compile-flags:-Zmir-opt-level=3
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _ = (0 .. 1).filter(|_| [1].iter().all(|_| true)).count();
diff --git a/src/test/ui/issues/issue-50471.rs b/src/test/ui/issues/issue-50471.rs
index 6868d481962..e728e45e60b 100644
--- a/src/test/ui/issues/issue-50471.rs
+++ b/src/test/ui/issues/issue-50471.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     assert!({false});
diff --git a/src/test/ui/issues/issue-50518.rs b/src/test/ui/issues/issue-50518.rs
index d776d181b62..653b52902d2 100644
--- a/src/test/ui/issues/issue-50518.rs
+++ b/src/test/ui/issues/issue-50518.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 use std::marker::PhantomData;
 
 struct Meta<A> {
diff --git a/src/test/ui/issues/issue-50761.rs b/src/test/ui/issues/issue-50761.rs
index 70b4bc8b755..59d4f9afdaa 100644
--- a/src/test/ui/issues/issue-50761.rs
+++ b/src/test/ui/issues/issue-50761.rs
@@ -1,6 +1,6 @@
 // Confirm that we don't accidentally divide or mod by zero in llvm_type
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 mod a {
     pub trait A {}
diff --git a/src/test/ui/issues/issue-50993.rs b/src/test/ui/issues/issue-50993.rs
index 772c45dee11..b170e09d02d 100644
--- a/src/test/ui/issues/issue-50993.rs
+++ b/src/test/ui/issues/issue-50993.rs
@@ -1,5 +1,5 @@
 // compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
 
 #![feature(no_core)]
diff --git a/src/test/ui/issues/issue-51655.rs b/src/test/ui/issues/issue-51655.rs
index 989fcc041a0..c2ad60fd8cf 100644
--- a/src/test/ui/issues/issue-51655.rs
+++ b/src/test/ui/issues/issue-51655.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 const PATH_DOT: &[u8] = &[b'.'];
diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs
index 7b79807e4d7..b5ebf156a27 100644
--- a/src/test/ui/issues/issue-51947.rs
+++ b/src/test/ui/issues/issue-51947.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "lib"]
 #![feature(linkage)]
diff --git a/src/test/ui/issues/issue-52992.rs b/src/test/ui/issues/issue-52992.rs
index c58656330e1..727dd43d574 100644
--- a/src/test/ui/issues/issue-52992.rs
+++ b/src/test/ui/issues/issue-52992.rs
@@ -2,7 +2,7 @@
 // implied bounds was causing outlives relations that were not
 // properly handled.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {}
 
diff --git a/src/test/ui/issues/issue-53419.rs b/src/test/ui/issues/issue-53419.rs
index bf6791734d4..64ac0b1c03b 100644
--- a/src/test/ui/issues/issue-53419.rs
+++ b/src/test/ui/issues/issue-53419.rs
@@ -1,4 +1,4 @@
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Foo {
     bar: dyn for<'r> Fn(usize, &'r dyn FnMut())
diff --git a/src/test/ui/issues/issue-5353.rs b/src/test/ui/issues/issue-5353.rs
index 808b73ec72f..cca17595051 100644
--- a/src/test/ui/issues/issue-5353.rs
+++ b/src/test/ui/issues/issue-5353.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-53568.rs b/src/test/ui/issues/issue-53568.rs
index 4d3b3f80a97..7644810c947 100644
--- a/src/test/ui/issues/issue-53568.rs
+++ b/src/test/ui/issues/issue-53568.rs
@@ -1,7 +1,7 @@
 // Regression test for an NLL-related ICE (#53568) -- we failed to
 // resolve inference variables in "custom type-ops".
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Future {
     type Item;
diff --git a/src/test/ui/issues/issue-53675-a-test-called-panic.rs b/src/test/ui/issues/issue-53675-a-test-called-panic.rs
index 8a35b36d46d..b8dca96946a 100644
--- a/src/test/ui/issues/issue-53675-a-test-called-panic.rs
+++ b/src/test/ui/issues/issue-53675-a-test-called-panic.rs
@@ -1,7 +1,7 @@
 // rust-lang/rust#53675: At one point the compiler errored when a test
 // named `panic` used the `assert!` macro in expression position.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: --test
 
 mod in_expression_position {
diff --git a/src/test/ui/issues/issue-54387.rs b/src/test/ui/issues/issue-54387.rs
index ac1033add0e..7aee500744d 100644
--- a/src/test/ui/issues/issue-54387.rs
+++ b/src/test/ui/issues/issue-54387.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub struct GstRc {
     _obj: *const (),
diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/issues/issue-54521-1.rs
index d6a14a6e11f..9bda7635eff 100644
--- a/src/test/ui/issues/issue-54521-1.rs
+++ b/src/test/ui/issues/issue-54521-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test checks that the `remove extra angle brackets` error doesn't happen for some
 // potential edge-cases..
diff --git a/src/test/ui/issues/issue-54943-1.rs b/src/test/ui/issues/issue-54943-1.rs
index 8d3a4e72de4..eca27819a40 100644
--- a/src/test/ui/issues/issue-54943-1.rs
+++ b/src/test/ui/issues/issue-54943-1.rs
@@ -1,7 +1,7 @@
 // This test is a minimal version of an ICE in the dropck-eyepatch tests
 // found in the fix for #54943.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn foo<T>(_t: T) {
 }
diff --git a/src/test/ui/issues/issue-54943-2.rs b/src/test/ui/issues/issue-54943-2.rs
index 41ca7c14982..c32f85dbe1a 100644
--- a/src/test/ui/issues/issue-54943-2.rs
+++ b/src/test/ui/issues/issue-54943-2.rs
@@ -2,7 +2,7 @@
 // found in the fix for #54943. In particular, this test is in unreachable
 // code as the initial fix for this ICE only worked if the code was reachable.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn foo<T>(_t: T) {
 }
diff --git a/src/test/ui/issues/issue-54943-3.rs b/src/test/ui/issues/issue-54943-3.rs
index 185077bd684..a9cc99c79d0 100644
--- a/src/test/ui/issues/issue-54943-3.rs
+++ b/src/test/ui/issues/issue-54943-3.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // FIXME(#54943) This test targets the scenario where proving the WF requirements requires
 // knowing the value of the `_` type present in the user type annotation - unfortunately, figuring
 // out the value of that `_` requires type-checking the surrounding code, but that code is dead,
diff --git a/src/test/ui/issues/issue-5500-1.rs b/src/test/ui/issues/issue-5500-1.rs
index 56f5ce9901e..edbbe33c66f 100644
--- a/src/test/ui/issues/issue-5500-1.rs
+++ b/src/test/ui/issues/issue-5500-1.rs
@@ -2,7 +2,7 @@
 // is OK because the test is here to check that the compiler doesn't ICE (cf.
 // #5500).
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct TrieMapIterator<'a> {
     node: &'a usize
diff --git a/src/test/ui/issues/issue-5572.rs b/src/test/ui/issues/issue-5572.rs
index e5963a7c435..db26b0372a6 100644
--- a/src/test/ui/issues/issue-5572.rs
+++ b/src/test/ui/issues/issue-5572.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-56128.rs b/src/test/ui/issues/issue-56128.rs
index 3a3eccdc33c..32d87586cf4 100644
--- a/src/test/ui/issues/issue-56128.rs
+++ b/src/test/ui/issues/issue-56128.rs
@@ -1,7 +1,7 @@
 // Regression test for #56128. When this `pub(super) use...` gets
 // exploded in the HIR, we were not handling ids correctly.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 mod bar {
     pub(super) use self::baz::{x, y};
diff --git a/src/test/ui/issues/issue-56202.rs b/src/test/ui/issues/issue-56202.rs
index bd222b7fe98..6d6f23d2844 100644
--- a/src/test/ui/issues/issue-56202.rs
+++ b/src/test/ui/issues/issue-56202.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait FooTrait {}
 
diff --git a/src/test/ui/issues/issue-56411-aux.rs b/src/test/ui/issues/issue-56411-aux.rs
index bd689e913ab..6880a8a98d2 100644
--- a/src/test/ui/issues/issue-56411-aux.rs
+++ b/src/test/ui/issues/issue-56411-aux.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct T {}
 
diff --git a/src/test/ui/issues/issue-57156.rs b/src/test/ui/issues/issue-57156.rs
index f20b0f41c7f..b6cd8c927a2 100644
--- a/src/test/ui/issues/issue-57156.rs
+++ b/src/test/ui/issues/issue-57156.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Foo<Args> {
     type Output;
diff --git a/src/test/ui/issues/issue-57162.rs b/src/test/ui/issues/issue-57162.rs
index abe0887e927..7ba2f9cea84 100644
--- a/src/test/ui/issues/issue-57162.rs
+++ b/src/test/ui/issues/issue-57162.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Foo {}
 impl Foo for dyn Send {}
diff --git a/src/test/ui/issues/issue-57410-1.rs b/src/test/ui/issues/issue-57410-1.rs
index dab77bd660c..c4247b3b11c 100644
--- a/src/test/ui/issues/issue-57410-1.rs
+++ b/src/test/ui/issues/issue-57410-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Originally from #53925.
 // Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
diff --git a/src/test/ui/issues/issue-57410.rs b/src/test/ui/issues/issue-57410.rs
index 0d697e5619d..de7ae4b3c07 100644
--- a/src/test/ui/issues/issue-57410.rs
+++ b/src/test/ui/issues/issue-57410.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
 
diff --git a/src/test/ui/issues/issue-5754.rs b/src/test/ui/issues/issue-5754.rs
index 78e87013359..a629729d395 100644
--- a/src/test/ui/issues/issue-5754.rs
+++ b/src/test/ui/issues/issue-5754.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
 
diff --git a/src/test/ui/issues/issue-5884.rs b/src/test/ui/issues/issue-5884.rs
index ad7067bb9b1..acb3e19765e 100644
--- a/src/test/ui/issues/issue-5884.rs
+++ b/src/test/ui/issues/issue-5884.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-5900.rs b/src/test/ui/issues/issue-5900.rs
index 5ac7acc8e39..850e67db629 100644
--- a/src/test/ui/issues/issue-5900.rs
+++ b/src/test/ui/issues/issue-5900.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-5950.rs b/src/test/ui/issues/issue-5950.rs
index 19e0cfc7f27..5c2250e25fc 100644
--- a/src/test/ui/issues/issue-5950.rs
+++ b/src/test/ui/issues/issue-5950.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-60662.rs b/src/test/ui/issues/issue-60662.rs
index fe4eaff742d..dca1e5979ef 100644
--- a/src/test/ui/issues/issue-60662.rs
+++ b/src/test/ui/issues/issue-60662.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z unpretty=hir
 
 #![feature(existential_type)]
diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout
index 5acfdf9ed53..139808974c6 100644
--- a/src/test/ui/issues/issue-60662.stdout
+++ b/src/test/ui/issues/issue-60662.stdout
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z unpretty=hir
 
 #![feature(existential_type)]
diff --git a/src/test/ui/issues/issue-6341.rs b/src/test/ui/issues/issue-6341.rs
index 2b23ccd2586..2fb0fee60ba 100644
--- a/src/test/ui/issues/issue-6341.rs
+++ b/src/test/ui/issues/issue-6341.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 #[derive(PartialEq)]
diff --git a/src/test/ui/issues/issue-6470.rs b/src/test/ui/issues/issue-6470.rs
index 49a313f90de..305f46c6d4e 100644
--- a/src/test/ui/issues/issue-6470.rs
+++ b/src/test/ui/issues/issue-6470.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
 
diff --git a/src/test/ui/issues/issue-6557.rs b/src/test/ui/issues/issue-6557.rs
index aa091ca594a..70b301d3d9c 100644
--- a/src/test/ui/issues/issue-6557.rs
+++ b/src/test/ui/issues/issue-6557.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-6898.rs b/src/test/ui/issues/issue-6898.rs
index 608c0c80716..6bf20d71d1f 100644
--- a/src/test/ui/issues/issue-6898.rs
+++ b/src/test/ui/issues/issue-6898.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // pretty-expanded FIXME #23616
 
 use std::mem;
diff --git a/src/test/ui/issues/issue-6991.rs b/src/test/ui/issues/issue-6991.rs
index e835edea113..aae67637f2c 100644
--- a/src/test/ui/issues/issue-6991.rs
+++ b/src/test/ui/issues/issue-6991.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_upper_case_globals)]
 
diff --git a/src/test/ui/issues/issue-7268.rs b/src/test/ui/issues/issue-7268.rs
index 0b94fabf385..69901e97894 100644
--- a/src/test/ui/issues/issue-7268.rs
+++ b/src/test/ui/issues/issue-7268.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-7607-2.rs b/src/test/ui/issues/issue-7607-2.rs
index 8b5c8505d3a..e336e0b47b2 100644
--- a/src/test/ui/issues/issue-7607-2.rs
+++ b/src/test/ui/issues/issue-7607-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs b/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs
index 619256c7871..9570386730a 100644
--- a/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs
+++ b/src/test/ui/issues/issue-7673-cast-generically-implemented-trait.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs
index e4dafc073ab..653d002fa61 100644
--- a/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs
+++ b/src/test/ui/issues/issue-8171-default-method-self-inherit-builtin-trait.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-8398.rs b/src/test/ui/issues/issue-8398.rs
index a65c667b08e..5fe88854b39 100644
--- a/src/test/ui/issues/issue-8398.rs
+++ b/src/test/ui/issues/issue-8398.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-8521.rs b/src/test/ui/issues/issue-8521.rs
index 7007c8a3a98..02a0e14d55e 100644
--- a/src/test/ui/issues/issue-8521.rs
+++ b/src/test/ui/issues/issue-8521.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 trait Foo1 {}
 
 trait A {}
diff --git a/src/test/ui/issues/issue-8578.rs b/src/test/ui/issues/issue-8578.rs
index 4cc21234796..6ffb721372a 100644
--- a/src/test/ui/issues/issue-8578.rs
+++ b/src/test/ui/issues/issue-8578.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
diff --git a/src/test/ui/issues/issue-9110.rs b/src/test/ui/issues/issue-9110.rs
index 30acd61a34a..f3bab42ee16 100644
--- a/src/test/ui/issues/issue-9110.rs
+++ b/src/test/ui/issues/issue-9110.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 #![allow(non_snake_case)]
diff --git a/src/test/ui/issues/issue-9243.rs b/src/test/ui/issues/issue-9243.rs
index e877dd64922..78237421c98 100644
--- a/src/test/ui/issues/issue-9243.rs
+++ b/src/test/ui/issues/issue-9243.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Regression test for issue 9243
 #![allow(non_upper_case_globals)]
diff --git a/src/test/ui/issues/issue-9249.rs b/src/test/ui/issues/issue-9249.rs
index e4e9c459719..b1f2bd7569a 100644
--- a/src/test/ui/issues/issue-9249.rs
+++ b/src/test/ui/issues/issue-9249.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/issues/issue-9719.rs b/src/test/ui/issues/issue-9719.rs
index 1e38ab9c6c2..58eb32b111d 100644
--- a/src/test/ui/issues/issue-9719.rs
+++ b/src/test/ui/issues/issue-9719.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs
index ac98724d037..f26e157bc70 100644
--- a/src/test/ui/lint/command-line-lint-group-allow.rs
+++ b/src/test/ui/lint/command-line-lint-group-allow.rs
@@ -1,5 +1,5 @@
 // compile-flags: -A bad-style
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _InappropriateCamelCasing = true;
diff --git a/src/test/ui/lint/command-line-lint-group-warn.rs b/src/test/ui/lint/command-line-lint-group-warn.rs
index 73dd656f60c..d3a4201ba60 100644
--- a/src/test/ui/lint/command-line-lint-group-warn.rs
+++ b/src/test/ui/lint/command-line-lint-group-warn.rs
@@ -1,5 +1,5 @@
 // compile-flags: -W bad-style
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _InappropriateCamelCasing = true;
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
index d52c651ce38..9fce66a0a83 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // run-rustfix
 
 #![warn(ellipsis_inclusive_range_patterns)]
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
index 5174a8b8b7e..f886e778b59 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // run-rustfix
 
 #![warn(ellipsis_inclusive_range_patterns)]
diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
index 7d3fd441ae5..4cb35e907c8 100644
--- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
+++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(box_syntax)]
 #![feature(box_patterns)]
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
index 8872c0047fd..47063a7c267 100644
--- a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
+++ b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_parens)]
 
diff --git a/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
index e4be1edc5d7..3802e01a775 100644
--- a/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
+++ b/src/test/ui/lint/issue-54099-camel-case-underscore-types.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![forbid(non_camel_case_types)]
 #![allow(dead_code)]
diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
index 3a52996195c..eda9e2cdfaa 100644
--- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs
+++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(ellipsis_inclusive_range_patterns)]
 #![allow(unreachable_patterns)]
diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
index 8ca5af21630..95da4efa590 100644
--- a/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
+++ b/src/test/ui/lint/lint-lowercase-static-const-pattern-rename.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // Issue #7526: lowercase static constants in patterns look like bindings
 
 // This is similar to lint-lowercase-static-const-pattern.rs, except it
diff --git a/src/test/ui/lint/lint-non-camel-case-variant.rs b/src/test/ui/lint/lint-non-camel-case-variant.rs
index 1f06b283984..434e24c1d27 100644
--- a/src/test/ui/lint/lint-non-camel-case-variant.rs
+++ b/src/test/ui/lint/lint-non-camel-case-variant.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(non_camel_case_types)]
 
diff --git a/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
index c2fdfb4fe42..d025ee94854 100644
--- a/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
+++ b/src/test/ui/lint/lint-non-camel-case-with-trailing-underscores.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code)]
 // This is ok because we often use the trailing underscore to mean 'prime'
diff --git a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
index 9a6487d2542..5bec82ce1a6 100644
--- a/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
+++ b/src/test/ui/lint/lint-non-snake-case-no-lowercase-equivalent.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
diff --git a/src/test/ui/lint/lint-nonstandard-style-unicode.rs b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
index a0b4130c3e9..40f0a676381 100644
--- a/src/test/ui/lint/lint-nonstandard-style-unicode.rs
+++ b/src/test/ui/lint/lint-nonstandard-style-unicode.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/lint/lint-output-format-2.rs b/src/test/ui/lint/lint-output-format-2.rs
index c9b33f06e21..32a41179965 100644
--- a/src/test/ui/lint/lint-output-format-2.rs
+++ b/src/test/ui/lint/lint-output-format-2.rs
@@ -1,7 +1,7 @@
 // aux-build:lint_output_format.rs
 
 #![feature(unstable_test_feature)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 extern crate lint_output_format;
 use lint_output_format::{foo, bar};
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index a2031c2189a..652fd04bdf5 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:lint_stability.rs
 // aux-build:inherited_stability.rs
 // aux-build:stability_cfg1.rs
diff --git a/src/test/ui/lint/lint-type-overflow2.rs b/src/test/ui/lint/lint-type-overflow2.rs
index 507e8d07349..c1f874c079c 100644
--- a/src/test/ui/lint/lint-type-overflow2.rs
+++ b/src/test/ui/lint/lint-type-overflow2.rs
@@ -1,15 +1,13 @@
 // compile-flags: -O
-#![warn(overflowing_literals)]
-#![warn(const_err)]
-// compile-pass
 
-#[allow(unused_variables)]
+#![deny(overflowing_literals)]
+#![deny(const_err)]
 
 fn main() {
-    let x2: i8 = --128; //~ warn: literal out of range for i8
+    let x2: i8 = --128; //~ ERROR literal out of range for `i8`
 
-    let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
-    let x =  3.40282357e+38_f32; //~ warn: literal out of range for f32
-    let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
-    let x =  1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
+    let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
+    let x =  3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
+    let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
+    let x =  1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
 }
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
index c76e9e25d5a..761b095464f 100644
--- a/src/test/ui/lint/lint-type-overflow2.stderr
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -1,48 +1,38 @@
-warning: literal out of range for `i8`
-  --> $DIR/lint-type-overflow2.rs:9:20
+error: literal out of range for `i8`
+  --> $DIR/lint-type-overflow2.rs:7:20
    |
 LL |     let x2: i8 = --128;
    |                    ^^^
    |
 note: lint level defined here
-  --> $DIR/lint-type-overflow2.rs:2:9
+  --> $DIR/lint-type-overflow2.rs:3:9
    |
-LL | #![warn(overflowing_literals)]
+LL | #![deny(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for `f32`
-  --> $DIR/lint-type-overflow2.rs:11:14
+error: literal out of range for `f32`
+  --> $DIR/lint-type-overflow2.rs:9:14
    |
 LL |     let x = -3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for `f32`
-  --> $DIR/lint-type-overflow2.rs:12:14
+error: literal out of range for `f32`
+  --> $DIR/lint-type-overflow2.rs:10:14
    |
 LL |     let x =  3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for `f64`
-  --> $DIR/lint-type-overflow2.rs:13:14
+error: literal out of range for `f64`
+  --> $DIR/lint-type-overflow2.rs:11:14
    |
 LL |     let x = -1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: literal out of range for `f64`
-  --> $DIR/lint-type-overflow2.rs:14:14
+error: literal out of range for `f64`
+  --> $DIR/lint-type-overflow2.rs:12:14
    |
 LL |     let x =  1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: this expression will panic at runtime
-  --> $DIR/lint-type-overflow2.rs:9:18
-   |
-LL |     let x2: i8 = --128;
-   |                  ^^^^^ attempt to negate with overflow
-   |
-note: lint level defined here
-  --> $DIR/lint-type-overflow2.rs:3:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/lint-unknown-feature-default.rs b/src/test/ui/lint/lint-unknown-feature-default.rs
index e04363faf4b..aebc4f18085 100644
--- a/src/test/ui/lint/lint-unknown-feature-default.rs
+++ b/src/test/ui/lint/lint-unknown-feature-default.rs
@@ -4,7 +4,7 @@
 // FIXME(#44232) we should warn that this isn't used.
 #![feature(rust1)]
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 
 fn main() { }
diff --git a/src/test/ui/lint/lint-unknown-feature.rs b/src/test/ui/lint/lint-unknown-feature.rs
index c372a980bed..93fa7a6e96e 100644
--- a/src/test/ui/lint/lint-unknown-feature.rs
+++ b/src/test/ui/lint/lint-unknown-feature.rs
@@ -4,7 +4,7 @@
 // FIXME(#44232) we should warn that this isn't used.
 #![feature(rust1)]
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 
 fn main() {}
diff --git a/src/test/ui/lint/lints-in-foreign-macros.rs b/src/test/ui/lint/lints-in-foreign-macros.rs
index adef2f9e769..e381c81453b 100644
--- a/src/test/ui/lint/lints-in-foreign-macros.rs
+++ b/src/test/ui/lint/lints-in-foreign-macros.rs
@@ -1,5 +1,5 @@
 // aux-build:lints-in-foreign-macros.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_imports)] //~ missing documentation for crate [missing_docs]
 #![warn(missing_docs)]
diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs
index 60baa234987..d0adf6a875d 100644
--- a/src/test/ui/lint/must-use-ops.rs
+++ b/src/test/ui/lint/must-use-ops.rs
@@ -1,6 +1,6 @@
 // Issue #50124 - Test warning for unused operator expressions
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_must_use)]
 
diff --git a/src/test/ui/lint/must_use-array.rs b/src/test/ui/lint/must_use-array.rs
new file mode 100644
index 00000000000..97825dd2f6c
--- /dev/null
+++ b/src/test/ui/lint/must_use-array.rs
@@ -0,0 +1,47 @@
+#![deny(unused_must_use)]
+
+#[must_use]
+struct S;
+
+struct A;
+
+#[must_use]
+trait T {}
+
+impl T for A {}
+
+fn empty() -> [S; 0] {
+    []
+}
+
+fn singleton() -> [S; 1] {
+    [S]
+}
+
+fn many() -> [S; 4] {
+    [S, S, S, S]
+}
+
+fn array_of_impl_trait() -> [impl T; 2] {
+    [A, A]
+}
+
+fn impl_array() -> [(u8, Box<dyn T>); 2] {
+    [(0, Box::new(A)), (0, Box::new(A))]
+}
+
+fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
+    [[[S], [S]]]
+}
+
+fn main() {
+    empty(); // ok
+    singleton(); //~ ERROR unused array of `S` that must be used
+    many(); //~ ERROR unused array of `S` that must be used
+    ([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used
+    array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used
+    impl_array();
+    //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
+    array_of_arrays_of_arrays();
+    //~^ ERROR unused array of arrays of arrays of `S` that must be used
+}
diff --git a/src/test/ui/lint/must_use-array.stderr b/src/test/ui/lint/must_use-array.stderr
new file mode 100644
index 00000000000..a6dbd8e93d4
--- /dev/null
+++ b/src/test/ui/lint/must_use-array.stderr
@@ -0,0 +1,44 @@
+error: unused array of `S` that must be used
+  --> $DIR/must_use-array.rs:39:5
+   |
+LL |     singleton();
+   |     ^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must_use-array.rs:1:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: unused array of `S` that must be used
+  --> $DIR/must_use-array.rs:40:5
+   |
+LL |     many();
+   |     ^^^^^^^
+
+error: unused array of `S` in tuple element 0 that must be used
+  --> $DIR/must_use-array.rs:41:6
+   |
+LL |     ([S], 0, ());
+   |      ^^^
+
+error: unused array of implementers of `T` that must be used
+  --> $DIR/must_use-array.rs:42:5
+   |
+LL |     array_of_impl_trait();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused array of boxed `T` trait objects in tuple element 1 that must be used
+  --> $DIR/must_use-array.rs:43:5
+   |
+LL |     impl_array();
+   |     ^^^^^^^^^^^^^
+
+error: unused array of arrays of arrays of `S` that must be used
+  --> $DIR/must_use-array.rs:45:5
+   |
+LL |     array_of_arrays_of_arrays();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/lint/must_use-trait.rs b/src/test/ui/lint/must_use-trait.rs
index 23df4fa6132..0aa751443a0 100644
--- a/src/test/ui/lint/must_use-trait.rs
+++ b/src/test/ui/lint/must_use-trait.rs
@@ -17,6 +17,23 @@ fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant {
     Anon {}
 }
 
+fn get_boxed_critical() -> Box<dyn Critical> {
+    Box::new(Anon {})
+}
+
+fn get_nested_boxed_critical() -> Box<Box<dyn Critical>> {
+    Box::new(Box::new(Anon {}))
+}
+
+fn get_critical_tuple() -> (u32, Box<dyn Critical>, impl Critical, ()) {
+    (0, get_boxed_critical(), get_critical(), ())
+}
+
 fn main() {
     get_critical(); //~ ERROR unused implementer of `Critical` that must be used
+    get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used
+    get_nested_boxed_critical();
+    //~^ ERROR unused boxed boxed `Critical` trait object that must be used
+    get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1
+    //~^ ERROR unused implementer of `Critical` in tuple element 2
 }
diff --git a/src/test/ui/lint/must_use-trait.stderr b/src/test/ui/lint/must_use-trait.stderr
index 7e2b2f67964..be74362e29d 100644
--- a/src/test/ui/lint/must_use-trait.stderr
+++ b/src/test/ui/lint/must_use-trait.stderr
@@ -1,5 +1,5 @@
 error: unused implementer of `Critical` that must be used
-  --> $DIR/must_use-trait.rs:21:5
+  --> $DIR/must_use-trait.rs:33:5
    |
 LL |     get_critical();
    |     ^^^^^^^^^^^^^^^
@@ -10,5 +10,29 @@ note: lint level defined here
 LL | #![deny(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unused boxed `Critical` trait object that must be used
+  --> $DIR/must_use-trait.rs:34:5
+   |
+LL |     get_boxed_critical();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed boxed `Critical` trait object that must be used
+  --> $DIR/must_use-trait.rs:35:5
+   |
+LL |     get_nested_boxed_critical();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed `Critical` trait object in tuple element 1 that must be used
+  --> $DIR/must_use-trait.rs:37:5
+   |
+LL |     get_critical_tuple();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused implementer of `Critical` in tuple element 2 that must be used
+  --> $DIR/must_use-trait.rs:37:5
+   |
+LL |     get_critical_tuple();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/lint/not_found.rs b/src/test/ui/lint/not_found.rs
index 0b5a4eb7851..979a67b1558 100644
--- a/src/test/ui/lint/not_found.rs
+++ b/src/test/ui/lint/not_found.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // this tests the `unknown_lint` lint, especially the suggestions
 
diff --git a/src/test/ui/lint/reasons.rs b/src/test/ui/lint/reasons.rs
index eba91d92afb..5320987040a 100644
--- a/src/test/ui/lint/reasons.rs
+++ b/src/test/ui/lint/reasons.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(lint_reasons)]
 
diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs
index 64e59512073..c145bd256d8 100644
--- a/src/test/ui/lint/type-overflow.rs
+++ b/src/test/ui/lint/type-overflow.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![warn(overflowing_literals)]
 
 fn main() {
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.rs b/src/test/ui/lint/unreachable_pub-pub_crate.rs
index 6739c7f096b..27b437b22eb 100644
--- a/src/test/ui/lint/unreachable_pub-pub_crate.rs
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.rs
@@ -4,7 +4,7 @@
 // suggestions to use `crate` given when it is on). When that feature becomes
 // stable, this test can be deleted.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 
 #![allow(unused)]
diff --git a/src/test/ui/lint/unreachable_pub.rs b/src/test/ui/lint/unreachable_pub.rs
index 12726b6ecae..545281604ea 100644
--- a/src/test/ui/lint/unreachable_pub.rs
+++ b/src/test/ui/lint/unreachable_pub.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(crate_visibility_modifier)]
 
diff --git a/src/test/ui/lint/unused_import_warning_issue_45268.rs b/src/test/ui/lint/unused_import_warning_issue_45268.rs
index 0bd77511135..68a5819c9c7 100644
--- a/src/test/ui/lint/unused_import_warning_issue_45268.rs
+++ b/src/test/ui/lint/unused_import_warning_issue_45268.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused_imports)] // Warning explanation here, it's OK
 
diff --git a/src/test/ui/lint/unused_labels.rs b/src/test/ui/lint/unused_labels.rs
index 26ab9fbe5c8..d234a2fb1a0 100644
--- a/src/test/ui/lint/unused_labels.rs
+++ b/src/test/ui/lint/unused_labels.rs
@@ -2,7 +2,7 @@
 // should also deal with the edge cases where a label is shadowed,
 // within nested loops
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(label_break_value)]
 #![warn(unused_labels)]
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
index 4462c53152a..185bfacea80 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -1,5 +1,5 @@
 // compile-flags: --error-format pretty-json -Zunstable-options
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
index 07d96d5c482..396395a17f7 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -8,8 +8,8 @@
   "spans": [
     {
       "file_name": "$DIR/unused_parens_json_suggestion.rs",
-      "byte_start": 576,
-      "byte_end": 589,
+      "byte_start": 611,
+      "byte_end": 624,
       "line_start": 15,
       "line_end": 15,
       "column_start": 14,
@@ -36,8 +36,8 @@
       "spans": [
         {
           "file_name": "$DIR/unused_parens_json_suggestion.rs",
-          "byte_start": 422,
-          "byte_end": 435,
+          "byte_start": 457,
+          "byte_end": 470,
           "line_start": 10,
           "line_end": 10,
           "column_start": 9,
@@ -66,8 +66,8 @@
       "spans": [
         {
           "file_name": "$DIR/unused_parens_json_suggestion.rs",
-          "byte_start": 576,
-          "byte_end": 589,
+          "byte_start": 611,
+          "byte_end": 624,
           "line_start": 15,
           "line_end": 15,
           "column_start": 14,
diff --git a/src/test/ui/lint/use-redundant.rs b/src/test/ui/lint/use-redundant.rs
index 328f8232baf..6ec2af06801 100644
--- a/src/test/ui/lint/use-redundant.rs
+++ b/src/test/ui/lint/use-redundant.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![warn(unused_imports)]
 
 use crate::foo::Bar; //~ WARNING first import
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs
index 93f322ab368..316ee64072d 100644
--- a/src/test/ui/loops/loops-reject-duplicate-labels-2.rs
+++ b/src/test/ui/loops/loops-reject-duplicate-labels-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // ignore-tidy-linelength
 
diff --git a/src/test/ui/loops/loops-reject-duplicate-labels.rs b/src/test/ui/loops/loops-reject-duplicate-labels.rs
index 27f9862f70d..5ed8b2f416e 100644
--- a/src/test/ui/loops/loops-reject-duplicate-labels.rs
+++ b/src/test/ui/loops/loops-reject-duplicate-labels.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // ignore-tidy-linelength
 
diff --git a/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs
index 435ad3391a0..9047fbb95a2 100644
--- a/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs
+++ b/src/test/ui/loops/loops-reject-labels-shadowing-lifetimes.rs
@@ -1,7 +1,7 @@
 // Issue #21633: reject duplicate loop labels in function bodies.
 // This is testing interaction between lifetime-params and labels.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
index 656ed6576e2..9bb6a253b7f 100644
--- a/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
+++ b/src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/test/ui/macros/macro-expanded-include/test.rs b/src/test/ui/macros/macro-expanded-include/test.rs
index fe697db9fbe..b8eb854b0b0 100644
--- a/src/test/ui/macros/macro-expanded-include/test.rs
+++ b/src/test/ui/macros/macro-expanded-include/test.rs
@@ -1,5 +1,5 @@
 // ignore-emscripten no asm! support
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(asm)]
 #![allow(unused)]
 
diff --git a/src/test/ui/macros/macro-path-prelude-pass.rs b/src/test/ui/macros/macro-path-prelude-pass.rs
index 3d35d53f777..8daa1c84f1d 100644
--- a/src/test/ui/macros/macro-path-prelude-pass.rs
+++ b/src/test/ui/macros/macro-path-prelude-pass.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(extern_prelude)]
 
diff --git a/src/test/ui/macros/macro-shadowing-relaxed.rs b/src/test/ui/macros/macro-shadowing-relaxed.rs
index 2477226ce21..b2a639218b9 100644
--- a/src/test/ui/macros/macro-shadowing-relaxed.rs
+++ b/src/test/ui/macros/macro-shadowing-relaxed.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:macro-in-other-crate.rs
 
 #![feature(decl_macro)]
diff --git a/src/test/ui/macros/macro-stmt-matchers.rs b/src/test/ui/macros/macro-stmt-matchers.rs
index 6e53eb05121..a643e50e995 100644
--- a/src/test/ui/macros/macro-stmt-matchers.rs
+++ b/src/test/ui/macros/macro-stmt-matchers.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 
 fn main() {
diff --git a/src/test/ui/macros/macro-tt-matchers.rs b/src/test/ui/macros/macro-tt-matchers.rs
index 17df72f36db..2ee41b0880e 100644
--- a/src/test/ui/macros/macro-tt-matchers.rs
+++ b/src/test/ui/macros/macro-tt-matchers.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 macro_rules! foo {
diff --git a/src/test/ui/macros/macro-use-scope.rs b/src/test/ui/macros/macro-use-scope.rs
index 03d57d22299..5e58fc9c1ed 100644
--- a/src/test/ui/macros/macro-use-scope.rs
+++ b/src/test/ui/macros/macro-use-scope.rs
@@ -1,6 +1,6 @@
 // aux-build:two_macros.rs
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 fn f() {
diff --git a/src/test/ui/macros/must-use-in-macro-55516.rs b/src/test/ui/macros/must-use-in-macro-55516.rs
index a5de32e5d2a..4b6b65ec48b 100644
--- a/src/test/ui/macros/must-use-in-macro-55516.rs
+++ b/src/test/ui/macros/must-use-in-macro-55516.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Wunused
 
 // make sure write!() can't hide its unused Result
diff --git a/src/test/ui/macros/trace-macro.rs b/src/test/ui/macros/trace-macro.rs
index efd658dd2b9..576120811db 100644
--- a/src/test/ui/macros/trace-macro.rs
+++ b/src/test/ui/macros/trace-macro.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z trace-macros
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     println!("Hello, World!");
diff --git a/src/test/ui/malformed/malformed-regressions.rs b/src/test/ui/malformed/malformed-regressions.rs
index b5c992440d4..c1a9d04e6d5 100644
--- a/src/test/ui/malformed/malformed-regressions.rs
+++ b/src/test/ui/malformed/malformed-regressions.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[doc] //~ WARN attribute must be of the form
 #[ignore()] //~ WARN attribute must be of the form
diff --git a/src/test/ui/maybe-bounds-where-cpass.rs b/src/test/ui/maybe-bounds-where-cpass.rs
index 860de200f62..d4bc05f7cb4 100644
--- a/src/test/ui/maybe-bounds-where-cpass.rs
+++ b/src/test/ui/maybe-bounds-where-cpass.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct S<T>(*const T) where T: ?Sized;
 
diff --git a/src/test/ui/methods/method-call-lifetime-args-subst-index.rs b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
index 4ee09dcdf19..8df58a3486e 100644
--- a/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
+++ b/src/test/ui/methods/method-call-lifetime-args-subst-index.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 struct S;
diff --git a/src/test/ui/methods/method-trait-object-with-hrtb.rs b/src/test/ui/methods/method-trait-object-with-hrtb.rs
index da2f13f5a2f..d1bee676c2f 100644
--- a/src/test/ui/methods/method-trait-object-with-hrtb.rs
+++ b/src/test/ui/methods/method-trait-object-with-hrtb.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Check that method probing ObjectCandidate works in the presence of
 // auto traits and/or HRTBs.
diff --git a/src/test/ui/missing/missing-semicolon-warning.rs b/src/test/ui/missing/missing-semicolon-warning.rs
index 11204af702a..d962a52139e 100644
--- a/src/test/ui/missing/missing-semicolon-warning.rs
+++ b/src/test/ui/missing/missing-semicolon-warning.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(unused)]
 
 macro_rules! m {
diff --git a/src/test/ui/never-assign-dead-code.rs b/src/test/ui/never-assign-dead-code.rs
index 6b047c35065..fd5fbc30611 100644
--- a/src/test/ui/never-assign-dead-code.rs
+++ b/src/test/ui/never-assign-dead-code.rs
@@ -1,7 +1,7 @@
 // Test that an assignment of type ! makes the rest of the block dead code.
 
 #![feature(never_type)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![warn(unused)]
 
 
diff --git a/src/test/ui/never_transmute_never.rs b/src/test/ui/never_transmute_never.rs
index ef78eaa2120..5bad756b876 100644
--- a/src/test/ui/never_transmute_never.rs
+++ b/src/test/ui/never_transmute_never.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type="lib"]
 
diff --git a/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs b/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs
index 8ed6554877e..7679bf22e3c 100644
--- a/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs
+++ b/src/test/ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that we propagate region relations from closures precisely when there is
 // more than one non-local lower bound.
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
index d1945f4864c..1df7c6114ee 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
@@ -4,7 +4,7 @@
 // regions is erased.
 
 // compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/constant.rs b/src/test/ui/nll/constant.rs
index 2bc40fcb327..b1ea2c906da 100644
--- a/src/test/ui/nll/constant.rs
+++ b/src/test/ui/nll/constant.rs
@@ -2,7 +2,7 @@
 // arbitrary types without ICEs.
 
 // compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 const HI: &str = "hi";
 
diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs
index 5c72225b11f..0f3d27d0665 100644
--- a/src/test/ui/nll/drop-may-dangle.rs
+++ b/src/test/ui/nll/drop-may-dangle.rs
@@ -3,7 +3,7 @@
 // including) the call to `use_x`. The `else` branch is not included.
 
 // compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 #![feature(dropck_eyepatch)]
diff --git a/src/test/ui/nll/empty-type-predicate.rs b/src/test/ui/nll/empty-type-predicate.rs
index 75431d40ce5..48073f8749e 100644
--- a/src/test/ui/nll/empty-type-predicate.rs
+++ b/src/test/ui/nll/empty-type-predicate.rs
@@ -3,7 +3,7 @@
 // `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
 // the unexpected region.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait T {}
 fn f() where dyn T: {}
diff --git a/src/test/ui/nll/extra-unused-mut.rs b/src/test/ui/nll/extra-unused-mut.rs
index 6d0d6e16a67..e9c8df46213 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
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(generators, nll)]
 #![deny(unused_mut)]
diff --git a/src/test/ui/nll/generator-distinct-lifetime.rs b/src/test/ui/nll/generator-distinct-lifetime.rs
index d479a61baa2..1bd39db35d9 100644
--- a/src/test/ui/nll/generator-distinct-lifetime.rs
+++ b/src/test/ui/nll/generator-distinct-lifetime.rs
@@ -6,7 +6,7 @@
 // over a yield -- because the data that is borrowed (`*x`) is not
 // stored on the stack.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn foo(x: &mut u32) {
     move || {
diff --git a/src/test/ui/nll/issue-16223.rs b/src/test/ui/nll/issue-16223.rs
index e7536275064..c1205ba96ad 100644
--- a/src/test/ui/nll/issue-16223.rs
+++ b/src/test/ui/nll/issue-16223.rs
@@ -13,7 +13,7 @@
 //    |
 //    = note: move occurs because the value has type `A`, which does not implement the `Copy` trait
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(box_patterns)]
 
diff --git a/src/test/ui/nll/issue-21114-ebfull.rs b/src/test/ui/nll/issue-21114-ebfull.rs
index 1fe4fffa324..5a5db1a17f3 100644
--- a/src/test/ui/nll/issue-21114-ebfull.rs
+++ b/src/test/ui/nll/issue-21114-ebfull.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::collections::HashMap;
 use std::sync::Mutex;
diff --git a/src/test/ui/nll/issue-21114-kixunil.rs b/src/test/ui/nll/issue-21114-kixunil.rs
index 80a85293e5a..32c97a651c5 100644
--- a/src/test/ui/nll/issue-21114-kixunil.rs
+++ b/src/test/ui/nll/issue-21114-kixunil.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn from_stdin(min: u64) -> Vec<u64> {
     use std::io::BufRead;
diff --git a/src/test/ui/nll/issue-22323-temp-destruction.rs b/src/test/ui/nll/issue-22323-temp-destruction.rs
index 6357c3ccef1..1add91b1bd0 100644
--- a/src/test/ui/nll/issue-22323-temp-destruction.rs
+++ b/src/test/ui/nll/issue-22323-temp-destruction.rs
@@ -1,7 +1,7 @@
 // rust-lang/rust#22323: regression test demonstrating that NLL
 // precisely tracks temporary destruction order.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _s = construct().borrow().consume_borrowed();
diff --git a/src/test/ui/nll/issue-30104.rs b/src/test/ui/nll/issue-30104.rs
index 27e519005f6..3f4818a28c8 100644
--- a/src/test/ui/nll/issue-30104.rs
+++ b/src/test/ui/nll/issue-30104.rs
@@ -1,6 +1,6 @@
 // Regression test for #30104
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
index 7e0ffd6cf36..bffff650158 100644
--- a/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
+++ b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // rust-lang/rust#32382: Borrow checker used to complain about
 // `foobar_3` in the `impl` below, presumably due to some interaction
diff --git a/src/test/ui/nll/issue-43058.rs b/src/test/ui/nll/issue-43058.rs
index c50473511f1..8bf9028690f 100644
--- a/src/test/ui/nll/issue-43058.rs
+++ b/src/test/ui/nll/issue-43058.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::borrow::Cow;
 
diff --git a/src/test/ui/nll/issue-47022.rs b/src/test/ui/nll/issue-47022.rs
index 3f8e0f5ad3d..ecd7071ecc7 100644
--- a/src/test/ui/nll/issue-47022.rs
+++ b/src/test/ui/nll/issue-47022.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct LoadedObject {
     bodies: Vec<Body>,
diff --git a/src/test/ui/nll/issue-50716-1.rs b/src/test/ui/nll/issue-50716-1.rs
index ec992959a66..1e602f27247 100644
--- a/src/test/ui/nll/issue-50716-1.rs
+++ b/src/test/ui/nll/issue-50716-1.rs
@@ -3,7 +3,7 @@
 // bounds derived from `Sized` requirements” that checks that the fixed compiler
 // accepts this code fragment with both AST and MIR borrow checkers.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Qey<Q: ?Sized>(Q);
 
diff --git a/src/test/ui/nll/issue-51351.rs b/src/test/ui/nll/issue-51351.rs
index b45477c7fb1..efffe80aae4 100644
--- a/src/test/ui/nll/issue-51351.rs
+++ b/src/test/ui/nll/issue-51351.rs
@@ -6,7 +6,7 @@
 // of the closure, as they were not present in the closure's generic
 // declarations otherwise.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn creash<'a>() {
     let x: &'a () = &();
diff --git a/src/test/ui/nll/issue-52078.rs b/src/test/ui/nll/issue-52078.rs
index 4b8e6c68075..935bf8cda5e 100644
--- a/src/test/ui/nll/issue-52078.rs
+++ b/src/test/ui/nll/issue-52078.rs
@@ -2,7 +2,7 @@
 // between `'a` and `'b` below due to inference variables introduced
 // during the normalization process.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Drain<'a, T: 'a> {
     _marker: ::std::marker::PhantomData<&'a T>,
diff --git a/src/test/ui/nll/issue-53119.rs b/src/test/ui/nll/issue-53119.rs
index 7a47a77f6bb..f5400aaad8b 100644
--- a/src/test/ui/nll/issue-53119.rs
+++ b/src/test/ui/nll/issue-53119.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::ops::Deref;
 
diff --git a/src/test/ui/nll/issue-53570.rs b/src/test/ui/nll/issue-53570.rs
index 81c50edfed1..25c1929b227 100644
--- a/src/test/ui/nll/issue-53570.rs
+++ b/src/test/ui/nll/issue-53570.rs
@@ -6,7 +6,7 @@
 // parameter `x` -- since `'b` cannot be expressed in the caller's
 // space, that got promoted th `'static`.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::cell::{RefCell, Ref};
 
diff --git a/src/test/ui/nll/issue-55344.rs b/src/test/ui/nll/issue-55344.rs
index 521d4d33d86..a65635585db 100644
--- a/src/test/ui/nll/issue-55344.rs
+++ b/src/test/ui/nll/issue-55344.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(unused_mut)]
 
diff --git a/src/test/ui/nll/issue-55651.rs b/src/test/ui/nll/issue-55651.rs
index 976098e40ad..73fce288f8b 100644
--- a/src/test/ui/nll/issue-55651.rs
+++ b/src/test/ui/nll/issue-55651.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(untagged_unions)]
 
diff --git a/src/test/ui/nll/issue-57280-1.rs b/src/test/ui/nll/issue-57280-1.rs
index e02d6a0cb5a..f9cea42e7c4 100644
--- a/src/test/ui/nll/issue-57280-1.rs
+++ b/src/test/ui/nll/issue-57280-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Foo<'a> {
     const C: &'a u32;
diff --git a/src/test/ui/nll/issue-57280.rs b/src/test/ui/nll/issue-57280.rs
index 776a0d359cd..65ca23cc88f 100644
--- a/src/test/ui/nll/issue-57280.rs
+++ b/src/test/ui/nll/issue-57280.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Foo {
     const BLAH: &'static str;
diff --git a/src/test/ui/nll/issue-61311-normalize.rs b/src/test/ui/nll/issue-61311-normalize.rs
index 1164e9ef2d6..9237c27f57e 100644
--- a/src/test/ui/nll/issue-61311-normalize.rs
+++ b/src/test/ui/nll/issue-61311-normalize.rs
@@ -1,7 +1,7 @@
 // Regression test for #61311
 // We would ICE after failing to normalize `Self::Proj` in the `impl` below.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub struct Unit;
 trait Obj {}
diff --git a/src/test/ui/nll/issue-61320-normalize.rs b/src/test/ui/nll/issue-61320-normalize.rs
index a36ccd36113..59bceed08f9 100644
--- a/src/test/ui/nll/issue-61320-normalize.rs
+++ b/src/test/ui/nll/issue-61320-normalize.rs
@@ -1,7 +1,7 @@
 // Regression test for #61320
 // This is the same issue as #61311, just a larger test case.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 pub struct AndThen<A, B, F>
 where
diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
index 3415c3eeabc..72212e9e70c 100644
--- a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/projection-return.rs b/src/test/ui/nll/projection-return.rs
index fdf3f594841..5c340434691 100644
--- a/src/test/ui/nll/projection-return.rs
+++ b/src/test/ui/nll/projection-return.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Zborrowck=mir
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
index 23caa59b6b7..1bbc896c270 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
+++ b/src/test/ui/nll/relate_tys/hr-fn-aau-eq-abu.rs
@@ -6,7 +6,7 @@
 // another -- effectively, the single lifetime `'a` is just inferred
 // to be the intersection of the two distinct lifetimes.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:-Zno-leak-check
 
 #![feature(nll)]
diff --git a/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
index bac9e26588c..4e8599b2e3f 100644
--- a/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
+++ b/src/test/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -2,7 +2,7 @@
 // function returning always its first argument can be upcast to one
 // that returns either first or second argument.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:-Zno-leak-check
 
 #![feature(nll)]
diff --git a/src/test/ui/nll/relate_tys/issue-48071.rs b/src/test/ui/nll/relate_tys/issue-48071.rs
index 72987629848..36cd57a1b2d 100644
--- a/src/test/ui/nll/relate_tys/issue-48071.rs
+++ b/src/test/ui/nll/relate_tys/issue-48071.rs
@@ -4,7 +4,7 @@
 // placeholder region, but in NLL land it would fail because we had
 // rewritten `'static` to a region variable.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Foo {
     fn foo(&self) { }
diff --git a/src/test/ui/nll/ty-outlives/issue-53789-1.rs b/src/test/ui/nll/ty-outlives/issue-53789-1.rs
index dc67c1a68aa..2293d7d4bbc 100644
--- a/src/test/ui/nll/ty-outlives/issue-53789-1.rs
+++ b/src/test/ui/nll/ty-outlives/issue-53789-1.rs
@@ -1,6 +1,6 @@
 // Regression test for #53789.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::collections::BTreeMap;
 
diff --git a/src/test/ui/nll/ty-outlives/issue-53789-2.rs b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
index 1b80be2eaff..313b615fe80 100644
--- a/src/test/ui/nll/ty-outlives/issue-53789-2.rs
+++ b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
@@ -1,6 +1,6 @@
 // Regression test for #53789.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::collections::BTreeMap;
 use std::ops::Range;
diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs
index cda3915849e..147ea203489 100644
--- a/src/test/ui/nll/ty-outlives/issue-55756.rs
+++ b/src/test/ui/nll/ty-outlives/issue-55756.rs
@@ -16,7 +16,7 @@
 // Fixed by tweaking the solver to recognize that the constraint from
 // the environment duplicates one from the trait.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type="lib"]
 
diff --git a/src/test/ui/nll/ty-outlives/projection-body.rs b/src/test/ui/nll/ty-outlives/projection-body.rs
index 2e105ece8b5..148120d848b 100644
--- a/src/test/ui/nll/ty-outlives/projection-body.rs
+++ b/src/test/ui/nll/ty-outlives/projection-body.rs
@@ -1,7 +1,7 @@
 // Test that when we infer the lifetime to a subset of the fn body, it
 // works out.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait MyTrait<'a> {
     type Output;
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
index 452a8ea4f85..b9c9611e38c 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs
@@ -3,7 +3,7 @@
 // we don't even propagate constraints from the closures to the callers.
 
 // compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
index 73147666111..4613dd29ef8 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs
@@ -4,7 +4,7 @@
 //
 // Regression test for #53121.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait MyTrait<'a> {
     type Output;
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
index 7c7d64a8cb4..89328c2ef1b 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs
@@ -4,7 +4,7 @@
 // MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says
 // so).
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait MyTrait<'a> {
     type Output: 'a;
diff --git a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
index f61f54f80a7..27c3e89c1c3 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
+++ b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs
@@ -1,5 +1,5 @@
 // compile-flags:-Zborrowck=mir -Zverbose
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that we assume that universal types like `T` outlive the
 // function body.
diff --git a/src/test/ui/nll/user-annotations/downcast-infer.rs b/src/test/ui/nll/user-annotations/downcast-infer.rs
index 23b76bb1964..3efea713630 100644
--- a/src/test/ui/nll/user-annotations/downcast-infer.rs
+++ b/src/test/ui/nll/user-annotations/downcast-infer.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Check that we don't try to downcast `_` when type-checking the annotation.
 fn main() {
diff --git a/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs b/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs
index 6b9d30f5ab4..66b3110d2af 100644
--- a/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs
+++ b/src/test/ui/nll/user-annotations/issue-54570-bootstrapping.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test is reduced from a scenario pnkfelix encountered while
 // bootstrapping the compiler.
diff --git a/src/test/ui/no-warn-on-field-replace-issue-34101.rs b/src/test/ui/no-warn-on-field-replace-issue-34101.rs
index af6ccf35d53..eb701b9184e 100644
--- a/src/test/ui/no-warn-on-field-replace-issue-34101.rs
+++ b/src/test/ui/no-warn-on-field-replace-issue-34101.rs
@@ -18,7 +18,7 @@
 
 
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Foo(String);
 
diff --git a/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs b/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs
index 25a9c2ed98e..af6585aadae 100644
--- a/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs
+++ b/src/test/ui/non_modrs_mods_and_inline_mods/non_modrs_mods_and_inline_mods.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 mod x;
 
diff --git a/src/test/ui/object-safety/object-safety-by-value-self.rs b/src/test/ui/object-safety/object-safety-by-value-self.rs
index a8b1ddfaba7..c74a4d1cbbb 100644
--- a/src/test/ui/object-safety/object-safety-by-value-self.rs
+++ b/src/test/ui/object-safety/object-safety-by-value-self.rs
@@ -1,6 +1,6 @@
 // Check that a trait with by-value self is considered object-safe.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(trivial_casts)]
 
diff --git a/src/test/ui/object-safety/object-safety-phantom-fn.rs b/src/test/ui/object-safety/object-safety-phantom-fn.rs
index 59ed12c78f0..3ffeb81c1cb 100644
--- a/src/test/ui/object-safety/object-safety-phantom-fn.rs
+++ b/src/test/ui/object-safety/object-safety-phantom-fn.rs
@@ -1,6 +1,6 @@
 // Check that `Self` appearing in a phantom fn does not make a trait not object safe.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 trait Baz {
diff --git a/src/test/ui/panic_implementation-closures.rs b/src/test/ui/panic_implementation-closures.rs
index 92c333b4092..b96125aa952 100644
--- a/src/test/ui/panic_implementation-closures.rs
+++ b/src/test/ui/panic_implementation-closures.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![crate_type = "rlib"]
 #![no_std]
diff --git a/src/test/ui/parser/bounds-obj-parens.rs b/src/test/ui/parser/bounds-obj-parens.rs
index 1e0f9e40cdc..ae8112b61c6 100644
--- a/src/test/ui/parser/bounds-obj-parens.rs
+++ b/src/test/ui/parser/bounds-obj-parens.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(bare_trait_objects)]
 
diff --git a/src/test/ui/parser/impl-qpath.rs b/src/test/ui/parser/impl-qpath.rs
index 78c41f481af..ab45649f4de 100644
--- a/src/test/ui/parser/impl-qpath.rs
+++ b/src/test/ui/parser/impl-qpath.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z parse-only
 
 impl <*const u8>::AssocTy {} // OK
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.rs b/src/test/ui/parser/macro-bad-delimiter-ident.rs
index 987c955d1dc..13dec95435b 100644
--- a/src/test/ui/parser/macro-bad-delimiter-ident.rs
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.rs
@@ -1,3 +1,3 @@
 fn main() {
-    foo! bar < //~ ERROR expected `(` or `{`, found `<`
+    foo! bar < //~ ERROR expected open delimiter
 }
diff --git a/src/test/ui/parser/macro-bad-delimiter-ident.stderr b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
index 6a17d39e8bf..e97839a4f4a 100644
--- a/src/test/ui/parser/macro-bad-delimiter-ident.stderr
+++ b/src/test/ui/parser/macro-bad-delimiter-ident.stderr
@@ -1,8 +1,8 @@
-error: expected `(` or `{`, found `<`
-  --> $DIR/macro-bad-delimiter-ident.rs:2:14
+error: expected open delimiter
+  --> $DIR/macro-bad-delimiter-ident.rs:2:10
    |
 LL |     foo! bar <
-   |              ^ expected `(` or `{`
+   |          ^^^ expected open delimiter
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/trailing-plus-in-bounds.rs b/src/test/ui/parser/trailing-plus-in-bounds.rs
index 3213e068053..33c30d73108 100644
--- a/src/test/ui/parser/trailing-plus-in-bounds.rs
+++ b/src/test/ui/parser/trailing-plus-in-bounds.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(box_syntax)]
 #![allow(bare_trait_objects)]
diff --git a/src/test/ui/parser/trait-plusequal-splitting.rs b/src/test/ui/parser/trait-plusequal-splitting.rs
index c655a15d268..26ac3ead6a5 100644
--- a/src/test/ui/parser/trait-plusequal-splitting.rs
+++ b/src/test/ui/parser/trait-plusequal-splitting.rs
@@ -1,6 +1,6 @@
 // Fixes issue where `+` in generics weren't parsed if they were part of a `+=`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Whitespace<T: Clone + = ()> { t: T }
 struct TokenSplit<T: Clone +=  ()> { t: T }
diff --git a/src/test/ui/parser/underscore-suffix-for-string.rs b/src/test/ui/parser/underscore-suffix-for-string.rs
index bcd0b24c750..dd0599b4ab3 100644
--- a/src/test/ui/parser/underscore-suffix-for-string.rs
+++ b/src/test/ui/parser/underscore-suffix-for-string.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     let _ = "Foo"_;
diff --git a/src/test/ui/print-fuel/print-fuel.rs b/src/test/ui/print-fuel/print-fuel.rs
index 1bd39242669..e4434695446 100644
--- a/src/test/ui/print-fuel/print-fuel.rs
+++ b/src/test/ui/print-fuel/print-fuel.rs
@@ -3,7 +3,7 @@
 
 // (#55495: The --error-format is to sidestep an issue in our test harness)
 // compile-flags: --error-format human -Z print-fuel=foo
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct S1(u8, u16, u8);
 struct S2(u8, u16, u8);
diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs
index 4d2a0e27fd1..b96348640fa 100644
--- a/src/test/ui/print_type_sizes/anonymous.rs
+++ b/src/test/ui/print_type_sizes/anonymous.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // All of the types that occur in this function are uninteresting, in
 // that one cannot control the sizes of these types with the same sort
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
index 360c9958686..f165526dffa 100644
--- a/src/test/ui/print_type_sizes/generics.rs
+++ b/src/test/ui/print_type_sizes/generics.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 // This file illustrates how generics are handled: types have to be
 // monomorphized, in the MIR of the original function in which they
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
index 1b1d8174201..4cb7ae03b54 100644
--- a/src/test/ui/print_type_sizes/multiple_types.rs
+++ b/src/test/ui/print_type_sizes/multiple_types.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This file illustrates that when multiple structural types occur in
 // a function, every one of them is included in the output.
diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs
index 0127261b2b7..d9845fd6d70 100644
--- a/src/test/ui/print_type_sizes/niche-filling.rs
+++ b/src/test/ui/print_type_sizes/niche-filling.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 // This file illustrates how niche-filling enums are handled,
 // modelled after cases like `Option<&u32>`, `Option<bool>` and such.
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
index 7307c0fd8b4..4495a7770a7 100644
--- a/src/test/ui/print_type_sizes/no_duplicates.rs
+++ b/src/test/ui/print_type_sizes/no_duplicates.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 // This file illustrates that when the same type occurs repeatedly
 // (even if multiple functions), it is only printed once in the
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
index ec3efd6923a..dce4a61ef33 100644
--- a/src/test/ui/print_type_sizes/packed.rs
+++ b/src/test/ui/print_type_sizes/packed.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 // This file illustrates how packing is handled; it should cause
 // the elimination of padding that would normally be introduced
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
index c6d927cb1e5..1f894c5e252 100644
--- a/src/test/ui/print_type_sizes/padding.rs
+++ b/src/test/ui/print_type_sizes/padding.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This file illustrates how padding is handled: alignment
 // requirements can lead to the introduction of padding, either before
diff --git a/src/test/ui/print_type_sizes/repr-align.rs b/src/test/ui/print_type_sizes/repr-align.rs
index fd452f411c5..1e6f7ccca40 100644
--- a/src/test/ui/print_type_sizes/repr-align.rs
+++ b/src/test/ui/print_type_sizes/repr-align.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 // This file illustrates how padding is handled: alignment
 // requirements can lead to the introduction of padding, either before
diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs
index 6816bb71a00..7aad2715bc0 100644
--- a/src/test/ui/print_type_sizes/repr_int_c.rs
+++ b/src/test/ui/print_type_sizes/repr_int_c.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)`
 // variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug).
diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs
index 14245d0dc9a..ae4e492456a 100644
--- a/src/test/ui/print_type_sizes/uninhabited.rs
+++ b/src/test/ui/print_type_sizes/uninhabited.rs
@@ -1,5 +1,8 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
+// ignore-pass
+// ^-- needed because `--pass check` does not emit the output needed.
+//     FIXME: consider using an attribute instead of side-effects.
 
 #![feature(never_type)]
 #![feature(start)]
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
index aa2d25a3926..77e2b4befba 100644
--- a/src/test/ui/print_type_sizes/variants.rs
+++ b/src/test/ui/print_type_sizes/variants.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Z print-type-sizes
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // This file illustrates two things:
 //
diff --git a/src/test/ui/privacy/issue-57264-1.rs b/src/test/ui/privacy/issue-57264-1.rs
index dcffdc3d4ef..5ef6a61fea1 100644
--- a/src/test/ui/privacy/issue-57264-1.rs
+++ b/src/test/ui/privacy/issue-57264-1.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:issue-57264-1.rs
 
 extern crate issue_57264_1;
diff --git a/src/test/ui/privacy/issue-57264-2.rs b/src/test/ui/privacy/issue-57264-2.rs
index 79d0d2c7cd7..4d5c9cfa1d5 100644
--- a/src/test/ui/privacy/issue-57264-2.rs
+++ b/src/test/ui/privacy/issue-57264-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:issue-57264-2.rs
 
 extern crate issue_57264_2;
diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs
index 61c6130e470..ef50875dcf6 100644
--- a/src/test/ui/privacy/private-in-public-existential.rs
+++ b/src/test/ui/privacy/private-in-public-existential.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(existential_type)]
 #![deny(private_in_public)]
diff --git a/src/test/ui/privacy/private-in-public-expr-pat.rs b/src/test/ui/privacy/private-in-public-expr-pat.rs
index a3e53bdf45d..5c9ecd13b09 100644
--- a/src/test/ui/privacy/private-in-public-expr-pat.rs
+++ b/src/test/ui/privacy/private-in-public-expr-pat.rs
@@ -1,6 +1,6 @@
 // Patterns and expressions are not interface parts and don't produce private-in-public errors.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct Priv1(usize);
 struct Priv2;
diff --git a/src/test/ui/privacy/restricted/lookup-ignores-private.rs b/src/test/ui/privacy/restricted/lookup-ignores-private.rs
index 419d521748c..240ce1e2b03 100644
--- a/src/test/ui/privacy/restricted/lookup-ignores-private.rs
+++ b/src/test/ui/privacy/restricted/lookup-ignores-private.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(warnings)]
 
 mod foo {
diff --git a/src/test/ui/proc-macro/attributes-included.rs b/src/test/ui/proc-macro/attributes-included.rs
index 0ab17a1f3b3..4769607ff39 100644
--- a/src/test/ui/proc-macro/attributes-included.rs
+++ b/src/test/ui/proc-macro/attributes-included.rs
@@ -1,5 +1,5 @@
 // aux-build:attributes-included.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused)]
 
diff --git a/src/test/ui/proc-macro/auxiliary/generate-mod.rs b/src/test/ui/proc-macro/auxiliary/generate-mod.rs
index 8b41e8b3b3e..e950f7d62d6 100644
--- a/src/test/ui/proc-macro/auxiliary/generate-mod.rs
+++ b/src/test/ui/proc-macro/auxiliary/generate-mod.rs
@@ -1,6 +1,7 @@
 // run-pass
 // force-host
 // no-prefer-dynamic
+// ignore-pass
 
 #![crate_type = "proc-macro"]
 
diff --git a/src/test/ui/proc-macro/derive-helper-shadowed.rs b/src/test/ui/proc-macro/derive-helper-shadowed.rs
index 0388e647b58..e299454e0fc 100644
--- a/src/test/ui/proc-macro/derive-helper-shadowed.rs
+++ b/src/test/ui/proc-macro/derive-helper-shadowed.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 // aux-build:derive-helper-shadowed-2.rs
 
diff --git a/src/test/ui/proc-macro/derive-in-mod.rs b/src/test/ui/proc-macro/derive-in-mod.rs
index e6b91324f95..8b5d4e9d09c 100644
--- a/src/test/ui/proc-macro/derive-in-mod.rs
+++ b/src/test/ui/proc-macro/derive-in-mod.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 
 extern crate test_macros;
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
index 2615db3e119..2495e72751b 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // aux-build:test-macros.rs
 
diff --git a/src/test/ui/proc-macro/edition-imports-2018.rs b/src/test/ui/proc-macro/edition-imports-2018.rs
index f8d6bc5e078..5a77cd4ef4f 100644
--- a/src/test/ui/proc-macro/edition-imports-2018.rs
+++ b/src/test/ui/proc-macro/edition-imports-2018.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // aux-build:edition-imports-2015.rs
 
diff --git a/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
index 25a2a376147..a6e64e1b1b1 100644
--- a/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
+++ b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 extern crate proc_macro;
diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs
index 6d3e5ec198d..2e20a3de6bf 100644
--- a/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs
+++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 
 #[macro_use(Empty)]
diff --git a/src/test/ui/proc-macro/issue-53481.rs b/src/test/ui/proc-macro/issue-53481.rs
index 2fbde5fedb9..ae10a3baa3e 100644
--- a/src/test/ui/proc-macro/issue-53481.rs
+++ b/src/test/ui/proc-macro/issue-53481.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 
 #[macro_use]
diff --git a/src/test/ui/proc-macro/macro-use-attr.rs b/src/test/ui/proc-macro/macro-use-attr.rs
index d1b1430fb5d..b101c09ed54 100644
--- a/src/test/ui/proc-macro/macro-use-attr.rs
+++ b/src/test/ui/proc-macro/macro-use-attr.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 
 #[macro_use]
diff --git a/src/test/ui/proc-macro/macro-use-bang.rs b/src/test/ui/proc-macro/macro-use-bang.rs
index d39c42267fb..9d30f48846d 100644
--- a/src/test/ui/proc-macro/macro-use-bang.rs
+++ b/src/test/ui/proc-macro/macro-use-bang.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test-macros.rs
 
 #![feature(proc_macro_hygiene)]
diff --git a/src/test/ui/proc-macro/no-missing-docs.rs b/src/test/ui/proc-macro/no-missing-docs.rs
index e5a5f8beb45..e1e8218582f 100644
--- a/src/test/ui/proc-macro/no-missing-docs.rs
+++ b/src/test/ui/proc-macro/no-missing-docs.rs
@@ -1,7 +1,7 @@
 //! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs`
 //! warnings.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // force-host
 // no-prefer-dynamic
 
diff --git a/src/test/ui/range/range_traits-4.rs b/src/test/ui/range/range_traits-4.rs
index 52c706080f3..b8e88559b15 100644
--- a/src/test/ui/range/range_traits-4.rs
+++ b/src/test/ui/range/range_traits-4.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::ops::*;
 
diff --git a/src/test/ui/range/range_traits-5.rs b/src/test/ui/range/range_traits-5.rs
index a8c3e9b0d62..4aec7a4159a 100644
--- a/src/test/ui/range/range_traits-5.rs
+++ b/src/test/ui/range/range_traits-5.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::ops::*;
 
diff --git a/src/test/ui/range/range_traits-7.rs b/src/test/ui/range/range_traits-7.rs
index 548676063ca..c7b310562d1 100644
--- a/src/test/ui/range/range_traits-7.rs
+++ b/src/test/ui/range/range_traits-7.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 use std::ops::*;
 
diff --git a/src/test/ui/reachable/expr_andand.rs b/src/test/ui/reachable/expr_andand.rs
index 173116ae357..d37eb0a3b84 100644
--- a/src/test/ui/reachable/expr_andand.rs
+++ b/src/test/ui/reachable/expr_andand.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/ui/reachable/expr_oror.rs b/src/test/ui/reachable/expr_oror.rs
index ecfa072aa81..e95062de4d7 100644
--- a/src/test/ui/reachable/expr_oror.rs
+++ b/src/test/ui/reachable/expr_oror.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
index 5cbfe6ebebb..ee9e7a364b8 100644
--- a/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
+++ b/src/test/ui/regions/issue-56537-closure-uses-region-from-container.rs
@@ -8,7 +8,7 @@
 // follow the same lifetime-elision rules used elsehwere. See
 // rust-lang/rust#56537
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn willy_no_annot<'w>(p: &'w str, q: &str) -> &'w str {
     let free_dumb = |_x| { p }; // no type annotation at all
diff --git a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
index d6b36af9bd6..49de70ae013 100644
--- a/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
+++ b/src/test/ui/regions/region-bound-extra-bound-in-inherent-impl.rs
@@ -1,7 +1,7 @@
 // Test related to #22779. In this case, the impl is an inherent impl,
 // so it doesn't have to match any trait, so no error results.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 struct MySlice<'a, T:'a>(&'a mut [T]);
diff --git a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
index deef9ab15b0..4ce5daf3842 100644
--- a/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
+++ b/src/test/ui/regions/region-bound-same-bounds-in-trait-and-impl.rs
@@ -1,7 +1,7 @@
 // Test related to #22779, but where the `'a:'b` relation
 // appears in the trait too. No error here.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Tr<'a, T> {
     fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b;
diff --git a/src/test/ui/regions/region-object-lifetime-1.rs b/src/test/ui/regions/region-object-lifetime-1.rs
index ab24eda2c2d..e58bd31d9cb 100644
--- a/src/test/ui/regions/region-object-lifetime-1.rs
+++ b/src/test/ui/regions/region-object-lifetime-1.rs
@@ -1,7 +1,7 @@
 // Various tests related to testing how region inference works
 // with respect to the object receivers.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(warnings)]
 
 trait Foo {
diff --git a/src/test/ui/regions/region-object-lifetime-3.rs b/src/test/ui/regions/region-object-lifetime-3.rs
index cda48347061..c3c7c51767d 100644
--- a/src/test/ui/regions/region-object-lifetime-3.rs
+++ b/src/test/ui/regions/region-object-lifetime-3.rs
@@ -1,7 +1,7 @@
 // Various tests related to testing how region inference works
 // with respect to the object receivers.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(warnings)]
 
 trait Foo {
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
index d407bee416f..dcad2e81a54 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-2.rs
@@ -2,7 +2,7 @@
 // "projection gap": in this test, we know that `T: 'x`, and that is
 // enough to conclude that `T::Foo: 'x`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
index c19fa98e914..ff2e10804ae 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-3.rs
@@ -2,7 +2,7 @@
 // "projection gap": in this test, we know that `T::Foo: 'x`, and that
 // is (naturally) enough to conclude that `T::Foo: 'x`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
index 7a19d17152c..3596bf7e8c2 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-4.rs
@@ -2,7 +2,7 @@
 // "projection gap": in this test, we know that `T: 'x`, and that
 // is (naturally) enough to conclude that `T: 'x`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
index 045d2891490..fc4d1618401 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region-rev.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
index e087d65a5c7..d716cb9c55b 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-region.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
index 20b391c263c..39eb0842d3f 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type-rev.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-//compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
index 7f84441903f..561cad790f0 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-enum-type.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
index 07daa35a809..e1287c34bac 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region-rev.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
index 59da5fb0dc7..7f22ae23b85 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-region.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
index 096069c0ca4..367f7a30201 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type-rev.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
index 3c8c4a1ef52..f780275b684 100644
--- a/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
+++ b/src/test/ui/regions/regions-outlives-nominal-type-struct-type.rs
@@ -3,7 +3,7 @@
 //
 // Rule OutlivesNominalType from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
diff --git a/src/test/ui/regions/regions-outlives-projection-hrtype.rs b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
index a6e976ebf8c..e7fe7b6c16d 100644
--- a/src/test/ui/regions/regions-outlives-projection-hrtype.rs
+++ b/src/test/ui/regions/regions-outlives-projection-hrtype.rs
@@ -5,7 +5,7 @@
 // `'r` is bound, that leads to badness. This test checks that
 // everything works.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 trait TheTrait {
diff --git a/src/test/ui/regions/regions-outlives-projection-trait-def.rs b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
index bad476d2779..928ed4baaa0 100644
--- a/src/test/ui/regions/regions-outlives-projection-trait-def.rs
+++ b/src/test/ui/regions/regions-outlives-projection-trait-def.rs
@@ -1,7 +1,7 @@
 // Test that `<F as Foo<'a>>::Type: 'b`, where `trait Foo<'a> { Type:
 // 'a; }`, does not require that `F: 'b`.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 trait SomeTrait<'a> {
diff --git a/src/test/ui/regions/regions-outlives-scalar.rs b/src/test/ui/regions/regions-outlives-scalar.rs
index ca012c4e1ed..5d0ed999380 100644
--- a/src/test/ui/regions/regions-outlives-scalar.rs
+++ b/src/test/ui/regions/regions-outlives-scalar.rs
@@ -1,7 +1,7 @@
 // Test that scalar values outlive all regions.
 // Rule OutlivesScalar from RFC 1214.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 struct Foo<'a> {
diff --git a/src/test/ui/removing-extern-crate.fixed b/src/test/ui/removing-extern-crate.fixed
index 71728e8a731..d2993dbc4a4 100644
--- a/src/test/ui/removing-extern-crate.fixed
+++ b/src/test/ui/removing-extern-crate.fixed
@@ -1,7 +1,7 @@
 // edition:2018
 // aux-build:removing-extern-crate.rs
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_idioms)]
 #![allow(unused_imports)]
diff --git a/src/test/ui/removing-extern-crate.rs b/src/test/ui/removing-extern-crate.rs
index b9cc1810e7c..22fdfc2b0ec 100644
--- a/src/test/ui/removing-extern-crate.rs
+++ b/src/test/ui/removing-extern-crate.rs
@@ -1,7 +1,7 @@
 // edition:2018
 // aux-build:removing-extern-crate.rs
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_idioms)]
 #![allow(unused_imports)]
diff --git a/src/test/ui/resolve/issue-57523.rs b/src/test/ui/resolve/issue-57523.rs
index c2a2f282542..5dc467d97e2 100644
--- a/src/test/ui/resolve/issue-57523.rs
+++ b/src/test/ui/resolve/issue-57523.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct S(u8);
 
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
index 7b499af632e..6e75977b590 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/bind-by-move-no-guards.rs
@@ -2,7 +2,7 @@
 // rust-lang/rust#2329), that starts passing with this feature in
 // place.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(bind_by_move_pattern_guards)]
 
diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
index aca6aa5f0f8..40588ca331e 100644
--- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
+++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-basic-examples.rs
@@ -1,6 +1,6 @@
 #![feature(bind_by_move_pattern_guards)]
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct A { a: Box<i32> }
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs
index 97061310d19..221b5cf6bfa 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/patterns.rs
@@ -1,5 +1,5 @@
 // aux-build:uninhabited.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![deny(unreachable_patterns)]
 #![feature(exhaustive_patterns)]
 
diff --git a/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
index 62f6e4463f9..dacaf489a90 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/variants_fictive_visibility.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:variants.rs
 
 extern crate variants;
diff --git a/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
index 438923e2924..b662685ae24 100644
--- a/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
+++ b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
@@ -6,7 +6,7 @@
 // strange errors. This test ensures that we do not give compilation
 // errors.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait MyIterator<'a>: Iterator where Self::Item: 'a { }
 
diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.rs b/src/test/ui/rfc-2166-underscore-imports/basic.rs
index 968da9c8d56..4766d75c8f4 100644
--- a/src/test/ui/rfc-2166-underscore-imports/basic.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/basic.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:underscore-imports.rs
 
 #![warn(unused_imports, unused_extern_crates)]
diff --git a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
index 95f7cae0b87..3662a466ded 100644
--- a/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/duplicate.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:duplicate.rs
 
 extern crate duplicate;
diff --git a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs
index 8b5bb8b3260..1cccc67e9ab 100644
--- a/src/test/ui/rfc-2166-underscore-imports/intercrate.rs
+++ b/src/test/ui/rfc-2166-underscore-imports/intercrate.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:underscore-imports.rs
 
 extern crate underscore_imports;
diff --git a/src/test/ui/rfc-2306/convert-id-const-with-gate.rs b/src/test/ui/rfc-2306/convert-id-const-with-gate.rs
index a82feb961f7..762dfbe4843 100644
--- a/src/test/ui/rfc-2306/convert-id-const-with-gate.rs
+++ b/src/test/ui/rfc-2306/convert-id-const-with-gate.rs
@@ -1,6 +1,6 @@
 // This test should pass since 'identity' is const fn.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 fn main() {
     const _FOO: u8 = ::std::convert::identity(42u8);
diff --git a/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs b/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs
index e66d4657566..710fdd57ed7 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z unpretty=expanded
 
 fn main() {
diff --git a/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout b/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout
index a6b15f9bbf6..c88f50c6813 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout
+++ b/src/test/ui/rfc-2497-if-let-chains/ast-pretty-check.stdout
@@ -4,7 +4,7 @@
 use ::std::prelude::v1::*;
 #[macro_use]
 extern crate std;
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z unpretty=expanded
 
 fn main() { if let 0 = 1 { } }
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs
index c521d04fda5..e796e37bbaa 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs
@@ -1,5 +1,5 @@
 // compile-flags: --cfg something
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(param_attrs)]
 
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
index 589e5fcc00e..9fc32d7cc55 100644
--- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait-impl.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z parse-only
 
 #![feature(generic_associated_types)]
diff --git a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
index 7fa71e4dd1a..7974ee9d39b 100644
--- a/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
+++ b/src/test/ui/rfc1598-generic-associated-types/parse/in-trait.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Z parse-only
 
 #![feature(generic_associated_types)]
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
index 82a7c2510e5..03492631cb7 100644
--- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
+++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs
@@ -3,7 +3,7 @@
 //FIXME(#44265): The lifetime shadowing and type parameter shadowing
 // should cause an error. Now it compiles (erroneously) and this will be addressed
 // by a future PR. Then remove the following:
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 trait Shadow<'a> {
     type Bar<'a>; // Error: shadowed lifetime
diff --git a/src/test/ui/rmeta-lib-pass.rs b/src/test/ui/rmeta-lib-pass.rs
index 4ab4117dd6c..fdd0516e4d6 100644
--- a/src/test/ui/rmeta-lib-pass.rs
+++ b/src/test/ui/rmeta-lib-pass.rs
@@ -1,7 +1,7 @@
 // compile-flags: --emit=metadata
 // aux-build:rmeta-rlib.rs
 // no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Check that building a metadata crate works with a dependent, rlib crate.
 // This is a cfail test since there is no executable to run.
diff --git a/src/test/ui/rmeta-pass.rs b/src/test/ui/rmeta-pass.rs
index 9c88de7a033..4f0db23f47d 100644
--- a/src/test/ui/rmeta-pass.rs
+++ b/src/test/ui/rmeta-pass.rs
@@ -1,7 +1,7 @@
 // compile-flags: --emit=metadata
 // aux-build:rmeta-meta.rs
 // no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Check that building a metadata crate works with a dependent, metadata-only
 // crate.
diff --git a/src/test/ui/rmeta-priv-warn.rs b/src/test/ui/rmeta-priv-warn.rs
index 823ce80623b..430c1f06f43 100644
--- a/src/test/ui/rmeta-priv-warn.rs
+++ b/src/test/ui/rmeta-priv-warn.rs
@@ -1,6 +1,6 @@
 // compile-flags: --emit=metadata
 // no-prefer-dynamic
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #[deny(warnings)]
 
diff --git a/src/test/ui/rust-2018/edition-lint-paths-2018.rs b/src/test/ui/rust-2018/edition-lint-paths-2018.rs
index 09b31beb775..2005d8f4d79 100644
--- a/src/test/ui/rust-2018/edition-lint-paths-2018.rs
+++ b/src/test/ui/rust-2018/edition-lint-paths-2018.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // compile-flags:--extern edition_lint_paths
 // aux-build:edition-lint-paths.rs
diff --git a/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs b/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs
index 323c6e105f5..950ad1f5046 100644
--- a/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs
+++ b/src/test/ui/rust-2018/edition-lint-uninferable-outlives.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(unused)]
 #![deny(explicit_outlives_requirements)]
diff --git a/src/test/ui/rust-2018/macro-use-warned-against.rs b/src/test/ui/rust-2018/macro-use-warned-against.rs
index 368b8daf243..6cd54aa68ae 100644
--- a/src/test/ui/rust-2018/macro-use-warned-against.rs
+++ b/src/test/ui/rust-2018/macro-use-warned-against.rs
@@ -1,6 +1,6 @@
 // aux-build:macro-use-warned-against.rs
 // aux-build:macro-use-warned-against2.rs
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(macro_use_extern_crate, unused)]
 
diff --git a/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs b/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs
index 3311ded5531..2d4cb6514ec 100644
--- a/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs
+++ b/src/test/ui/rust-2018/proc-macro-crate-in-paths.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // force-host
 // no-prefer-dynamic
 
diff --git a/src/test/ui/rust-2018/remove-extern-crate.fixed b/src/test/ui/rust-2018/remove-extern-crate.fixed
index 14575d18c23..7ddd2f547f0 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.fixed
+++ b/src/test/ui/rust-2018/remove-extern-crate.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 // edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
diff --git a/src/test/ui/rust-2018/remove-extern-crate.rs b/src/test/ui/rust-2018/remove-extern-crate.rs
index 0ee85f34e40..298b1614026 100644
--- a/src/test/ui/rust-2018/remove-extern-crate.rs
+++ b/src/test/ui/rust-2018/remove-extern-crate.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 // edition:2018
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:remove-extern-crate.rs
 // compile-flags:--extern remove_extern_crate
 
diff --git a/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed b/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed
index f0ca24714ed..7d136667b6d 100644
--- a/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed
+++ b/src/test/ui/rust-2018/suggestions-not-always-applicable.fixed
@@ -2,7 +2,7 @@
 // edition:2015
 // run-rustfix
 // rustfix-only-machine-applicable
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rust_2018_preview)]
 #![warn(rust_2018_compatibility)]
diff --git a/src/test/ui/rust-2018/suggestions-not-always-applicable.rs b/src/test/ui/rust-2018/suggestions-not-always-applicable.rs
index f0ca24714ed..7d136667b6d 100644
--- a/src/test/ui/rust-2018/suggestions-not-always-applicable.rs
+++ b/src/test/ui/rust-2018/suggestions-not-always-applicable.rs
@@ -2,7 +2,7 @@
 // edition:2015
 // run-rustfix
 // rustfix-only-machine-applicable
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rust_2018_preview)]
 #![warn(rust_2018_compatibility)]
diff --git a/src/test/ui/rust-2018/try-ident.fixed b/src/test/ui/rust-2018/try-ident.fixed
index 5af13934e84..f86a401cdf9 100644
--- a/src/test/ui/rust-2018/try-ident.fixed
+++ b/src/test/ui/rust-2018/try-ident.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_compatibility)]
 
diff --git a/src/test/ui/rust-2018/try-ident.rs b/src/test/ui/rust-2018/try-ident.rs
index faac13ab779..6cc6aa12ff7 100644
--- a/src/test/ui/rust-2018/try-ident.rs
+++ b/src/test/ui/rust-2018/try-ident.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_compatibility)]
 
diff --git a/src/test/ui/rust-2018/try-macro.fixed b/src/test/ui/rust-2018/try-macro.fixed
index c65f0fc30ef..7c1692fd7fb 100644
--- a/src/test/ui/rust-2018/try-macro.fixed
+++ b/src/test/ui/rust-2018/try-macro.fixed
@@ -1,7 +1,7 @@
 // Test that `try!` macros are rewritten.
 
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_compatibility)]
 #![allow(unused_variables)]
diff --git a/src/test/ui/rust-2018/try-macro.rs b/src/test/ui/rust-2018/try-macro.rs
index f435890a61d..2089d367be6 100644
--- a/src/test/ui/rust-2018/try-macro.rs
+++ b/src/test/ui/rust-2018/try-macro.rs
@@ -1,7 +1,7 @@
 // Test that `try!` macros are rewritten.
 
 // run-rustfix
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(rust_2018_compatibility)]
 #![allow(unused_variables)]
diff --git a/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs b/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs
index 0c2da1884b7..c6525869b02 100644
--- a/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs
+++ b/src/test/ui/rust-2018/uniform-paths/fn-local-enum.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 fn main() {
diff --git a/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs b/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs
index 5c3c753f9a7..9af520a0769 100644
--- a/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs
+++ b/src/test/ui/rust-2018/uniform-paths/from-decl-macro.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![feature(decl_macro)]
diff --git a/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs
index 9ec3a641131..446b2d05717 100644
--- a/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs
+++ b/src/test/ui/rust-2018/uniform-paths/issue-56596-2.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 // compile-flags: --extern issue_56596_2
 // aux-build:issue-56596-2.rs
diff --git a/src/test/ui/rust-2018/uniform-paths/prelude.rs b/src/test/ui/rust-2018/uniform-paths/prelude.rs
index 9a326b4c728..dca9587c5d3 100644
--- a/src/test/ui/rust-2018/uniform-paths/prelude.rs
+++ b/src/test/ui/rust-2018/uniform-paths/prelude.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 // Macro imported with `#[macro_use] extern crate`
diff --git a/src/test/ui/save-analysis/emit-notifications.rs b/src/test/ui/save-analysis/emit-notifications.rs
index 411acbb14db..e02f3ecc629 100644
--- a/src/test/ui/save-analysis/emit-notifications.rs
+++ b/src/test/ui/save-analysis/emit-notifications.rs
@@ -1,4 +1,7 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: -Zsave-analysis -Zemit-artifact-notifications
 // compile-flags: --crate-type rlib --error-format=json
+// ignore-pass
+// ^-- needed because otherwise, the .stderr file changes with --pass check
+
 pub fn foo() {}
diff --git a/src/test/ui/self/explicit-self-closures.rs b/src/test/ui/self/explicit-self-closures.rs
index 1217823da11..b409dfd7a1e 100644
--- a/src/test/ui/self/explicit-self-closures.rs
+++ b/src/test/ui/self/explicit-self-closures.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // Test to make sure that explicit self params work inside closures
 
diff --git a/src/test/ui/self/self-in-typedefs.rs b/src/test/ui/self/self-in-typedefs.rs
index e4fe7324ef3..73f23a9cc17 100644
--- a/src/test/ui/self/self-in-typedefs.rs
+++ b/src/test/ui/self/self-in-typedefs.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(untagged_unions)]
 
diff --git a/src/test/ui/self/self-type-param.rs b/src/test/ui/self/self-type-param.rs
index 57e01caa692..5eb8c3622e4 100644
--- a/src/test/ui/self/self-type-param.rs
+++ b/src/test/ui/self/self-type-param.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs b/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs
index 92b25cbf584..d9d7e66d0ca 100644
--- a/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-return.rs
@@ -5,7 +5,7 @@
 // (Normally, using `'static` would be preferred, but there are
 // times when that is not what you want.)
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 
diff --git a/src/test/ui/single-use-lifetime/one-use-in-struct.rs b/src/test/ui/single-use-lifetime/one-use-in-struct.rs
index 6c4d2a4a7ad..7285324ef63 100644
--- a/src/test/ui/single-use-lifetime/one-use-in-struct.rs
+++ b/src/test/ui/single-use-lifetime/one-use-in-struct.rs
@@ -2,7 +2,7 @@
 // even when they are only used once (since to not use a named
 // lifetime is illegal!)
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs b/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
index 4cdf1530a92..8efe806b6e6 100644
--- a/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
+++ b/src/test/ui/single-use-lifetime/two-uses-in-fn-argument-and-return.rs
@@ -1,7 +1,7 @@
 // Test that we DO NOT warn when lifetime name is used in
 // both the argument and return.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs b/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
index 375366e41c6..09b01d8b05b 100644
--- a/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
+++ b/src/test/ui/single-use-lifetime/two-uses-in-fn-arguments.rs
@@ -1,7 +1,7 @@
 // Test that we DO NOT warn when lifetime name is used multiple
 // arguments, or more than once in a single argument.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs b/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
index 63d03a2cf0a..eb85a148e60 100644
--- a/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
+++ b/src/test/ui/single-use-lifetime/two-uses-in-inherent-impl-header.rs
@@ -1,6 +1,6 @@
 // Test that we DO NOT warn for a lifetime used twice in an impl.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
diff --git a/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs b/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs
index d4a0d71713c..fd8c899f4fa 100644
--- a/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs
+++ b/src/test/ui/single-use-lifetime/two-uses-in-trait-impl.rs
@@ -1,7 +1,7 @@
 // Test that we DO NOT warn for a lifetime on an impl used in both
 // header and in an associated type.
 //
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(single_use_lifetimes)]
 #![allow(dead_code)]
diff --git a/src/test/ui/span/issue-24690.rs b/src/test/ui/span/issue-24690.rs
index 82899fc8965..f51ea55d4e6 100644
--- a/src/test/ui/span/issue-24690.rs
+++ b/src/test/ui/span/issue-24690.rs
@@ -1,7 +1,7 @@
 //! A test to ensure that helpful `note` messages aren't emitted more often
 //! than necessary.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Although there are three warnings, we should only get two "lint level defined
 // here" notes pointing at the `warnings` span, one for each error type.
diff --git a/src/test/ui/span/macro-span-replacement.rs b/src/test/ui/span/macro-span-replacement.rs
index c5998c1b403..04c7ab0ea58 100644
--- a/src/test/ui/span/macro-span-replacement.rs
+++ b/src/test/ui/span/macro-span-replacement.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused)]
 
diff --git a/src/test/ui/span/multispan-import-lint.rs b/src/test/ui/span/multispan-import-lint.rs
index 753c3599975..a49c60e1277 100644
--- a/src/test/ui/span/multispan-import-lint.rs
+++ b/src/test/ui/span/multispan-import-lint.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![warn(unused)]
 
diff --git a/src/test/ui/static/static-extern-type.rs b/src/test/ui/static/static-extern-type.rs
index 3666982b4e2..4fa48fa133b 100644
--- a/src/test/ui/static/static-extern-type.rs
+++ b/src/test/ui/static/static-extern-type.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(extern_types)]
 
 pub mod a {
diff --git a/src/test/ui/static_sized_requirement.rs b/src/test/ui/static_sized_requirement.rs
index 0ee0637232c..074280b7b66 100644
--- a/src/test/ui/static_sized_requirement.rs
+++ b/src/test/ui/static_sized_requirement.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(no_core, lang_items)]
 #![no_core]
diff --git a/src/test/ui/suggestions/issue-57672.rs b/src/test/ui/suggestions/issue-57672.rs
index 1773f72fc74..0881a631f3a 100644
--- a/src/test/ui/suggestions/issue-57672.rs
+++ b/src/test/ui/suggestions/issue-57672.rs
@@ -1,6 +1,6 @@
 // aux-build:foo.rs
 // compile-flags:--extern foo
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // edition:2018
 
 #![deny(unused_extern_crates)]
diff --git a/src/test/ui/test-on-macro.rs b/src/test/ui/test-on-macro.rs
index ad7424a1bbb..a238db6d716 100644
--- a/src/test/ui/test-on-macro.rs
+++ b/src/test/ui/test-on-macro.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags:--test
 
 #![deny(warnings)]
diff --git a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
index b1c2a000d4a..831372d4506 100644
--- a/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
+++ b/src/test/ui/test-shadowing/test-cant-be-shadowed.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // aux-build:test_macro.rs
 // compile-flags:--test
 
diff --git a/src/test/ui/test-should-panic-attr.rs b/src/test/ui/test-should-panic-attr.rs
index f936dd57587..9c38322fe96 100644
--- a/src/test/ui/test-should-panic-attr.rs
+++ b/src/test/ui/test-should-panic-attr.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // compile-flags: --test
 
 #[test]
diff --git a/src/test/ui/traits/conservative_impl_trait.rs b/src/test/ui/traits/conservative_impl_trait.rs
index 964e21779d5..4f25e57be56 100644
--- a/src/test/ui/traits/conservative_impl_trait.rs
+++ b/src/test/ui/traits/conservative_impl_trait.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // #39665
 
 fn batches(n: &u32) -> impl Iterator<Item=&u32> {
diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs
index 3dfcf03ce79..284baa48149 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs
+++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay.
 
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs
index 793d556d08c..d1b7bf6c2d7 100644
--- a/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-good.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // Regression test related to #56288. Check that a supertrait projection (of
 // `Output`) that references `Self` can be ok if it is referencing a projection (of
diff --git a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs
index 3e9f612a2af..83dfe6664a5 100644
--- a/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs
+++ b/src/test/ui/traits/trait-object-with-self-in-projection-output-repeated-supertrait.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // FIXME(eddyb) shorten the name so windows doesn't choke on it.
 #![crate_name = "trait_test"]
diff --git a/src/test/ui/traits/trait-privacy.rs b/src/test/ui/traits/trait-privacy.rs
index 6254157e25d..17a2e05e99f 100644
--- a/src/test/ui/traits/trait-privacy.rs
+++ b/src/test/ui/traits/trait-privacy.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 mod foo {
     pub use self::bar::T;
diff --git a/src/test/ui/traits/trait-with-dst.rs b/src/test/ui/traits/trait-with-dst.rs
index 86d6585bc61..a3e3b31df92 100644
--- a/src/test/ui/traits/trait-with-dst.rs
+++ b/src/test/ui/traits/trait-with-dst.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 // #55266
 
 struct VTable<DST: ?Sized> {
diff --git a/src/test/ui/traits/traits-issue-23003-overflow.rs b/src/test/ui/traits/traits-issue-23003-overflow.rs
index 06aa698ddef..5538e0303ed 100644
--- a/src/test/ui/traits/traits-issue-23003-overflow.rs
+++ b/src/test/ui/traits/traits-issue-23003-overflow.rs
@@ -2,7 +2,7 @@
 // types are required. This test now just compiles fine, since the
 // relevant rules that triggered the overflow were removed.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 use std::marker::PhantomData;
diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-poll.rs
index f63950ad5e9..d42e51c7405 100644
--- a/src/test/ui/try-poll.rs
+++ b/src/test/ui/try-poll.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(dead_code, unused)]
 
diff --git a/src/test/ui/type-alias-enum-variants-panic.rs b/src/test/ui/type-alias-enum-variants-panic.rs
deleted file mode 100644
index f97592f5d3b..00000000000
--- a/src/test/ui/type-alias-enum-variants-panic.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// ignore-tidy-linelength
-
-#![feature(type_alias_enum_variants)]
-
-#![allow(unreachable_code)]
-
-enum Enum { Variant {} }
-type Alias = Enum;
-
-fn main() {
-    Alias::Variant;
-    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
-    let Alias::Variant = panic!();
-    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Variant` [E0533]
-    let Alias::Variant(..) = panic!();
-    //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Variant` [E0164]
-}
diff --git a/src/test/ui/type-alias-enum-variants-panic.stderr b/src/test/ui/type-alias-enum-variants-panic.stderr
deleted file mode 100644
index 24cf85f5278..00000000000
--- a/src/test/ui/type-alias-enum-variants-panic.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
-  --> $DIR/type-alias-enum-variants-panic.rs:11:5
-   |
-LL |     Alias::Variant;
-   |     ^^^^^^^^^^^^^^
-
-error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Variant`
-  --> $DIR/type-alias-enum-variants-panic.rs:13:9
-   |
-LL |     let Alias::Variant = panic!();
-   |         ^^^^^^^^^^^^^^
-
-error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Variant`
-  --> $DIR/type-alias-enum-variants-panic.rs:15:9
-   |
-LL |     let Alias::Variant(..) = panic!();
-   |         ^^^^^^^^^^^^^^^^^^ not a tuple variant or struct
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs
deleted file mode 100644
index 295f8acf62f..00000000000
--- a/src/test/ui/type-alias-enum-variants-priority-2.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-enum E {
-    V(u8)
-}
-
-impl E {
-    fn V() {}
-}
-
-fn main() {
-    <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
-}
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr
deleted file mode 100644
index 10a4b44084a..00000000000
--- a/src/test/ui/type-alias-enum-variants-priority-2.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0061]: this function takes 1 parameter but 0 parameters were supplied
-  --> $DIR/type-alias-enum-variants-priority-2.rs:12:5
-   |
-LL |     V(u8)
-   |     ----- defined here
-...
-LL |     <E>::V();
-   |     ^^^^^^^^ expected 1 parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs
deleted file mode 100644
index 33f96553b57..00000000000
--- a/src/test/ui/type-alias-enum-variants-priority-3.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-enum E {
-    V
-}
-
-fn check() -> <E>::V {}
-//~^ ERROR expected type, found variant `V`
-
-fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs
deleted file mode 100644
index 82cd21b09d3..00000000000
--- a/src/test/ui/type-alias-enum-variants-priority.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-enum E {
-    V
-}
-
-trait Tr {
-    type V;
-    fn f() -> Self::V;
-}
-
-impl Tr for E {
-    type V = u8;
-    fn f() -> Self::V { 0 }
-    //~^ ERROR ambiguous associated item
-    //~| WARN this was previously accepted
-}
-
-fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants.rs b/src/test/ui/type-alias-enum-variants.rs
deleted file mode 100644
index c5974e55692..00000000000
--- a/src/test/ui/type-alias-enum-variants.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(type_alias_enum_variants)]
-
-type Alias<T> = Option<T>;
-
-fn main() {
-    let _ = Option::<u8>::None; // OK
-    let _ = Option::None::<u8>; // OK (Lint in future!)
-    let _ = Alias::<u8>::None; // OK
-    let _ = Alias::None::<u8>; // Error
-    //~^ type arguments are not allowed for this type
-}
diff --git a/src/test/ui/pattern/enum-variant-generic-args.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
index 85599530ea6..0c212096f92 100644
--- a/src/test/ui/pattern/enum-variant-generic-args.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
@@ -1,17 +1,22 @@
 // run-pass
 
-#![feature(type_alias_enum_variants)]
+// Check that resolving, in the value namespace, to an `enum` variant
+// through a type alias is well behaved in the presence of generics.
+// We check for situations with:
+// 1. a generic type `Alias<T>`, we can type-apply `Alias` when referring to a variant.
+// 2. a monotype `AliasFixed` of generic `Enum<T>`, we can refer to variants
+//    and the type-application of `T` in `AliasFixed` is kept.
 
 #![allow(irrefutable_let_patterns)]
 
-#[allow(dead_code)]
-enum Enum<T> { TSVariant(T), SVariant { v: T } }
+enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
 type Alias<T> = Enum<T>;
 type AliasFixed = Enum<()>;
 
 macro_rules! is_variant {
     (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
     (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
+    (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr));
     (@check $variant:ident, $matcher:tt, $expr:expr) => (
         assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
                 "expr does not have correct type");
@@ -40,4 +45,15 @@ fn main() {
     is_variant!(SVariant, Alias::<()>::SVariant { v: () });
 
     is_variant!(SVariant, AliasFixed::SVariant { v: () });
+
+    // Unit variant
+
+    is_variant!(UVariant, Enum::UVariant);
+    is_variant!(UVariant, Enum::UVariant::<()>);
+    is_variant!(UVariant, Enum::<()>::UVariant);
+
+    is_variant!(UVariant, Alias::UVariant);
+    is_variant!(UVariant, Alias::<()>::UVariant);
+
+    is_variant!(UVariant, AliasFixed::UVariant);
 }
diff --git a/src/test/ui/enum-variant-generic-args.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
index dd1f5f334df..f182c3ba8c7 100644
--- a/src/test/ui/enum-variant-generic-args.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs
@@ -1,6 +1,10 @@
-#![feature(type_alias_enum_variants)]
+// Checks that applied type arguments of enums, and aliases to them, are respected.
+// For example, `Self` is never a type constructor. Therefore, no types can be applied to it.
+//
+// We also check that the variant to an type-aliased enum cannot be type applied whether
+// that alias is generic or monomorphic.
 
-enum Enum<T> { TSVariant(T), SVariant { v: T } }
+enum Enum<T> { TSVariant(T), SVariant { v: T }, UVariant }
 type Alias<T> = Enum<T>;
 type AliasFixed = Enum<()>;
 
@@ -32,6 +36,16 @@ impl<T> Enum<T> {
         //~^^ ERROR type arguments are not allowed for this type [E0109]
         //~^^^ ERROR mismatched types [E0308]
     }
+
+    fn u_variant() {
+        Self::UVariant::<()>;
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        Self::<()>::UVariant;
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        Self::<()>::UVariant::<()>;
+        //~^ ERROR type arguments are not allowed for this type [E0109]
+        //~^^ ERROR type arguments are not allowed for this type [E0109]
+    }
 }
 
 fn main() {
@@ -70,4 +84,22 @@ fn main() {
     AliasFixed::<()>::SVariant::<()> { v: () };
     //~^ ERROR type arguments are not allowed for this type [E0109]
     //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+
+    // Unit variant
+
+    Enum::<()>::UVariant::<()>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    Alias::UVariant::<()>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    Alias::<()>::UVariant::<()>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+
+    AliasFixed::UVariant::<()>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    AliasFixed::<()>::UVariant;
+    //~^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
+    AliasFixed::<()>::UVariant::<()>;
+    //~^ ERROR type arguments are not allowed for this type [E0109]
+    //~^^ ERROR wrong number of type arguments: expected 0, found 1 [E0107]
 }
diff --git a/src/test/ui/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index 97b111a5c85..ee73622cb7b 100644
--- a/src/test/ui/enum-variant-generic-args.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:9:25
+  --> $DIR/enum-variant-generic-args.rs:13:25
    |
 LL |         Self::TSVariant(());
    |                         ^^ expected type parameter, found ()
@@ -8,19 +8,19 @@ LL |         Self::TSVariant(());
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:11:27
+  --> $DIR/enum-variant-generic-args.rs:15:27
    |
 LL |         Self::TSVariant::<()>(());
    |                           ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:13:16
+  --> $DIR/enum-variant-generic-args.rs:17:16
    |
 LL |         Self::<()>::TSVariant(());
    |                ^^ type argument not allowed
 
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:13:31
+  --> $DIR/enum-variant-generic-args.rs:17:31
    |
 LL |         Self::<()>::TSVariant(());
    |                               ^^ expected type parameter, found ()
@@ -29,19 +29,19 @@ LL |         Self::<()>::TSVariant(());
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:16:16
+  --> $DIR/enum-variant-generic-args.rs:20:16
    |
 LL |         Self::<()>::TSVariant::<()>(());
    |                ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:16:33
+  --> $DIR/enum-variant-generic-args.rs:20:33
    |
 LL |         Self::<()>::TSVariant::<()>(());
    |                                 ^^ type argument not allowed
 
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:22:29
+  --> $DIR/enum-variant-generic-args.rs:26:29
    |
 LL |         Self::SVariant { v: () };
    |                             ^^ expected type parameter, found ()
@@ -50,13 +50,13 @@ LL |         Self::SVariant { v: () };
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:24:26
+  --> $DIR/enum-variant-generic-args.rs:28:26
    |
 LL |         Self::SVariant::<()> { v: () };
    |                          ^^ type argument not allowed
 
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:24:35
+  --> $DIR/enum-variant-generic-args.rs:28:35
    |
 LL |         Self::SVariant::<()> { v: () };
    |                                   ^^ expected type parameter, found ()
@@ -65,13 +65,13 @@ LL |         Self::SVariant::<()> { v: () };
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:27:16
+  --> $DIR/enum-variant-generic-args.rs:31:16
    |
 LL |         Self::<()>::SVariant { v: () };
    |                ^^ type argument not allowed
 
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:27:35
+  --> $DIR/enum-variant-generic-args.rs:31:35
    |
 LL |         Self::<()>::SVariant { v: () };
    |                                   ^^ expected type parameter, found ()
@@ -80,19 +80,19 @@ LL |         Self::<()>::SVariant { v: () };
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:30:16
+  --> $DIR/enum-variant-generic-args.rs:34:16
    |
 LL |         Self::<()>::SVariant::<()> { v: () };
    |                ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:30:32
+  --> $DIR/enum-variant-generic-args.rs:34:32
    |
 LL |         Self::<()>::SVariant::<()> { v: () };
    |                                ^^ type argument not allowed
 
 error[E0308]: mismatched types
-  --> $DIR/enum-variant-generic-args.rs:30:41
+  --> $DIR/enum-variant-generic-args.rs:34:41
    |
 LL |         Self::<()>::SVariant::<()> { v: () };
    |                                         ^^ expected type parameter, found ()
@@ -101,90 +101,156 @@ LL |         Self::<()>::SVariant::<()> { v: () };
               found type `()`
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:40:29
+  --> $DIR/enum-variant-generic-args.rs:41:26
+   |
+LL |         Self::UVariant::<()>;
+   |                          ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:43:16
+   |
+LL |         Self::<()>::UVariant;
+   |                ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:45:16
+   |
+LL |         Self::<()>::UVariant::<()>;
+   |                ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:45:32
+   |
+LL |         Self::<()>::UVariant::<()>;
+   |                                ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:54:29
    |
 LL |     Enum::<()>::TSVariant::<()>(());
    |                             ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:43:24
+  --> $DIR/enum-variant-generic-args.rs:57:24
    |
 LL |     Alias::TSVariant::<()>(());
    |                        ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:45:30
+  --> $DIR/enum-variant-generic-args.rs:59:30
    |
 LL |     Alias::<()>::TSVariant::<()>(());
    |                              ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:48:29
+  --> $DIR/enum-variant-generic-args.rs:62:29
    |
 LL |     AliasFixed::TSVariant::<()>(());
    |                             ^^ type argument not allowed
 
 error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:50:18
+  --> $DIR/enum-variant-generic-args.rs:64:18
    |
 LL |     AliasFixed::<()>::TSVariant(());
    |                  ^^ unexpected type argument
 
 error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:52:18
+  --> $DIR/enum-variant-generic-args.rs:66:18
    |
 LL |     AliasFixed::<()>::TSVariant::<()>(());
    |                  ^^ unexpected type argument
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:52:35
+  --> $DIR/enum-variant-generic-args.rs:66:35
    |
 LL |     AliasFixed::<()>::TSVariant::<()>(());
    |                                   ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:58:28
+  --> $DIR/enum-variant-generic-args.rs:72:28
    |
 LL |     Enum::<()>::SVariant::<()> { v: () };
    |                            ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:61:23
+  --> $DIR/enum-variant-generic-args.rs:75:23
    |
 LL |     Alias::SVariant::<()> { v: () };
    |                       ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:63:29
+  --> $DIR/enum-variant-generic-args.rs:77:29
    |
 LL |     Alias::<()>::SVariant::<()> { v: () };
    |                             ^^ type argument not allowed
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:66:28
+  --> $DIR/enum-variant-generic-args.rs:80:28
    |
 LL |     AliasFixed::SVariant::<()> { v: () };
    |                            ^^ type argument not allowed
 
 error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:68:18
+  --> $DIR/enum-variant-generic-args.rs:82:18
    |
 LL |     AliasFixed::<()>::SVariant { v: () };
    |                  ^^ unexpected type argument
 
 error[E0107]: wrong number of type arguments: expected 0, found 1
-  --> $DIR/enum-variant-generic-args.rs:70:18
+  --> $DIR/enum-variant-generic-args.rs:84:18
    |
 LL |     AliasFixed::<()>::SVariant::<()> { v: () };
    |                  ^^ unexpected type argument
 
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/enum-variant-generic-args.rs:70:34
+  --> $DIR/enum-variant-generic-args.rs:84:34
    |
 LL |     AliasFixed::<()>::SVariant::<()> { v: () };
    |                                  ^^ type argument not allowed
 
-error: aborting due to 28 previous errors
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:90:28
+   |
+LL |     Enum::<()>::UVariant::<()>;
+   |                            ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:93:23
+   |
+LL |     Alias::UVariant::<()>;
+   |                       ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:95:29
+   |
+LL |     Alias::<()>::UVariant::<()>;
+   |                             ^^ type argument not allowed
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:98:28
+   |
+LL |     AliasFixed::UVariant::<()>;
+   |                            ^^ type argument not allowed
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:100:18
+   |
+LL |     AliasFixed::<()>::UVariant;
+   |                  ^^ unexpected type argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/enum-variant-generic-args.rs:102:18
+   |
+LL |     AliasFixed::<()>::UVariant::<()>;
+   |                  ^^ unexpected type argument
+
+error[E0109]: type arguments are not allowed for this type
+  --> $DIR/enum-variant-generic-args.rs:102:34
+   |
+LL |     AliasFixed::<()>::UVariant::<()>;
+   |                                  ^^ type argument not allowed
+
+error: aborting due to 39 previous errors
 
 Some errors have detailed explanations: E0107, E0109, E0308.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs
new file mode 100644
index 00000000000..fa3e1a35fc2
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs
@@ -0,0 +1,23 @@
+// Check that an `enum` variant is resolved, in the value namespace,
+// with higher priority than other inherent items when there is a conflict.
+
+enum E {
+    V(u8)
+}
+
+impl E {
+    fn V() {}
+}
+
+enum E2 {
+    V,
+}
+
+impl E2 {
+    const V: u8 = 0;
+}
+
+fn main() {
+    <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+    let _: u8 = <E2>::V; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
new file mode 100644
index 00000000000..0394ddab46c
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -0,0 +1,22 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5
+   |
+LL |     V(u8)
+   |     ----- defined here
+...
+LL |     <E>::V();
+   |     ^^^^^^^^ expected 1 parameter
+
+error[E0308]: mismatched types
+  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
+   |
+LL |     let _: u8 = <E2>::V;
+   |                 ^^^^^^^ expected u8, found enum `E2`
+   |
+   = note: expected type `u8`
+              found type `E2`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs
new file mode 100644
index 00000000000..7f69590400b
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs
@@ -0,0 +1,37 @@
+// Check that a projection `Self::V` in a trait implementation,
+// with an associated type named `V`, for an `enum` with a variant named `V`,
+// results in triggering the deny-by-default lint `ambiguous_associated_items`.
+// The lint suggests that qualified syntax should be used instead.
+// That is, the user would write `<Self as Tr>::V`.
+//
+// The rationale for this is that while `enum` variants do currently
+// not exist in the type namespace but solely in the value namespace,
+// RFC #2593 "Enum variant types", would add enum variants to the type namespace.
+// However, currently `enum` variants are resolved with high priority as
+// they are resolved as inherent associated items.
+// Should #2953 therefore be implemented, `Self::V` would suddenly switch
+// from referring to the associated type `V` instead of the variant `V`.
+// The lint exists to keep us forward compatible with #2593.
+//
+// As a closing note, provided that #2933 was implemented and
+// if `enum` variants were given lower priority than associated types,
+// it would be impossible to refer to the `enum` variant `V` whereas
+// the associated type could be referred to with qualified syntax as seen above.
+
+enum E {
+    V
+}
+
+trait Tr {
+    type V;
+    fn f() -> Self::V;
+}
+
+impl Tr for E {
+    type V = u8;
+    fn f() -> Self::V { 0 }
+    //~^ ERROR ambiguous associated item
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
index b8271807b83..f0dd689934f 100644
--- a/src/test/ui/type-alias-enum-variants-priority.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
@@ -1,5 +1,5 @@
 error: ambiguous associated item
-  --> $DIR/type-alias-enum-variants-priority.rs:14:15
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
    |
 LL |     fn f() -> Self::V { 0 }
    |               ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
@@ -8,12 +8,12 @@ LL |     fn f() -> Self::V { 0 }
    = 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
 note: `V` could refer to variant defined here
-  --> $DIR/type-alias-enum-variants-priority.rs:4:5
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5
    |
 LL |     V
    |     ^
 note: `V` could also refer to associated type defined here
-  --> $DIR/type-alias-enum-variants-priority.rs:8:5
+  --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5
    |
 LL |     type V;
    |     ^^^^^^^
diff --git a/src/test/ui/issues/issue-58006.rs b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs
index 1fb5fefa759..c1e56fc4caa 100644
--- a/src/test/ui/issues/issue-58006.rs
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.rs
@@ -1,4 +1,3 @@
-#![feature(type_alias_enum_variants)]
 pub enum Enum {
     A(usize),
 }
diff --git a/src/test/ui/issues/issue-58006.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
index c34e133c6c4..128a85e1563 100644
--- a/src/test/ui/issues/issue-58006.stderr
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr
@@ -1,5 +1,5 @@
 error[E0533]: expected unit struct/variant or constant, found tuple variant `<Self>::A`
-  --> $DIR/issue-58006.rs:9:13
+  --> $DIR/incorrect-variant-form-through-Self-issue-58006.rs:8:13
    |
 LL |             Self::A => (),
    |             ^^^^^^^
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs
new file mode 100644
index 00000000000..ce45d59198a
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+// Check that creating/matching on an enum variant through an alias with
+// the wrong braced/unit form is caught as an error.
+
+enum Enum { Braced {}, Unit, Tuple() }
+type Alias = Enum;
+
+fn main() {
+    Alias::Braced;
+    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
+    let Alias::Braced = panic!();
+    //~^ ERROR expected unit struct/variant or constant, found struct variant `<Alias>::Braced` [E0533]
+    let Alias::Braced(..) = panic!();
+    //~^ ERROR expected tuple struct/variant, found struct variant `<Alias>::Braced` [E0164]
+
+    Alias::Unit();
+    //~^ ERROR expected function, found enum variant `<Alias>::Unit`
+    let Alias::Unit() = panic!();
+    //~^ ERROR expected tuple struct/variant, found unit variant `<Alias>::Unit` [E0164]
+}
diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
new file mode 100644
index 00000000000..c1ea816b7fa
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr
@@ -0,0 +1,43 @@
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
+  --> $DIR/incorrect-variant-form-through-alias-caught.rs:10:5
+   |
+LL |     Alias::Braced;
+   |     ^^^^^^^^^^^^^
+
+error[E0533]: expected unit struct/variant or constant, found struct variant `<Alias>::Braced`
+  --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9
+   |
+LL |     let Alias::Braced = panic!();
+   |         ^^^^^^^^^^^^^
+
+error[E0164]: expected tuple struct/variant, found struct variant `<Alias>::Braced`
+  --> $DIR/incorrect-variant-form-through-alias-caught.rs:14:9
+   |
+LL |     let Alias::Braced(..) = panic!();
+   |         ^^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error[E0618]: expected function, found enum variant `<Alias>::Unit`
+  --> $DIR/incorrect-variant-form-through-alias-caught.rs:17:5
+   |
+LL | enum Enum { Braced {}, Unit, Tuple() }
+   |                        ---- `<Alias>::Unit` defined here
+...
+LL |     Alias::Unit();
+   |     ^^^^^^^^^^^--
+   |     |
+   |     call expression requires function
+help: `<Alias>::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+LL |     <Alias>::Unit;
+   |     ^^^^^^^^^^^^^
+
+error[E0164]: expected tuple struct/variant, found unit variant `<Alias>::Unit`
+  --> $DIR/incorrect-variant-form-through-alias-caught.rs:19:9
+   |
+LL |     let Alias::Unit() = panic!();
+   |         ^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0164, E0618.
+For more information about an error, try `rustc --explain E0164`.
diff --git a/src/test/ui/issues/issue-57866.rs b/src/test/ui/type-alias-enum-variants/issue-57866.rs
index 77c50e53868..058b58e174c 100644
--- a/src/test/ui/issues/issue-57866.rs
+++ b/src/test/ui/type-alias-enum-variants/issue-57866.rs
@@ -1,6 +1,4 @@
-// compile-pass
-
-#![feature(type_alias_enum_variants)]
+// build-pass (FIXME(62277): could be check-pass?)
 
 enum Outer<T> {
     A(T)
diff --git a/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs b/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs
index 21be61acb0c..bff04daed0d 100644
--- a/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs
+++ b/src/test/ui/type-alias-enum-variants/issue-61801-path-pattern-can-infer.rs
@@ -1,9 +1,7 @@
 // In this regression test we check that a path pattern referring to a unit variant
 // through a type alias is successful in inferring the generic argument.
 
-// compile-pass
-
-#![feature(type_alias_enum_variants)]
+// build-pass (FIXME(62277): could be check-pass?)
 
 enum Opt<T> {
     N,
diff --git a/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs
new file mode 100644
index 00000000000..c1153fa4dc7
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.rs
@@ -0,0 +1,14 @@
+// Check that a generic type for an `enum` admits type application
+// on both the type constructor and the generic type's variant.
+//
+// Also check that a type alias to said generic type admits type application
+// on the type constructor but *NOT* the variant.
+
+type Alias<T> = Option<T>;
+
+fn main() {
+    let _ = Option::<u8>::None; // OK
+    let _ = Option::None::<u8>; // OK (Lint in future!)
+    let _ = Alias::<u8>::None; // OK
+    let _ = Alias::None::<u8>; //~ ERROR type arguments are not allowed for this type
+}
diff --git a/src/test/ui/type-alias-enum-variants.stderr b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr
index 55f250fa7ee..a1064d69251 100644
--- a/src/test/ui/type-alias-enum-variants.stderr
+++ b/src/test/ui/type-alias-enum-variants/no-type-application-on-aliased-enum-variant.stderr
@@ -1,7 +1,7 @@
 error[E0109]: type arguments are not allowed for this type
-  --> $DIR/type-alias-enum-variants.rs:9:27
+  --> $DIR/no-type-application-on-aliased-enum-variant.rs:13:27
    |
-LL |     let _ = Alias::None::<u8>; // Error
+LL |     let _ = Alias::None::<u8>;
    |                           ^^ type argument not allowed
 
 error: aborting due to previous error
diff --git a/src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs b/src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs
new file mode 100644
index 00000000000..11f4b05d0bf
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.rs
@@ -0,0 +1,11 @@
+// Check that the compiler will resolve `<E>::V` to the variant `V` in the type namespace
+// but will reject this because `enum` variants do not exist in the type namespace.
+
+enum E {
+    V
+}
+
+fn check() -> <E>::V {}
+//~^ ERROR expected type, found variant `V`
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr
index b3451542a25..f190bfb6983 100644
--- a/src/test/ui/type-alias-enum-variants-priority-3.stderr
+++ b/src/test/ui/type-alias-enum-variants/resolve-to-enum-variant-in-type-namespace-and-error.stderr
@@ -1,5 +1,5 @@
 error: expected type, found variant `V`
-  --> $DIR/type-alias-enum-variants-priority-3.rs:7:15
+  --> $DIR/resolve-to-enum-variant-in-type-namespace-and-error.rs:8:15
    |
 LL | fn check() -> <E>::V {}
    |               ^^^^^^
diff --git a/src/test/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs b/src/test/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs
new file mode 100644
index 00000000000..39677733d52
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants/type-alias-enum-variants-pass.rs
@@ -0,0 +1,69 @@
+// run-pass
+
+// Check that it is possible to resolve, in the value namespace,
+// to an `enum` variant through a type alias. This includes `Self`.
+// Type qualified syntax `<Type>::Variant` also works when syntactically valid.
+
+#[derive(Debug, PartialEq, Eq)]
+enum Foo {
+    Bar(i32),
+    Baz { i: i32 },
+    Qux,
+}
+
+type FooAlias = Foo;
+type OptionAlias = Option<i32>;
+
+macro_rules! check_pat {
+    ($x:expr, $p:pat) => {
+        assert!(if let $p = $x { true } else { false });
+    };
+}
+
+impl Foo {
+    fn bar() -> Self {
+        let x = Self::Bar(3);
+        assert_eq!(x, <Self>::Bar(3));
+        check_pat!(x, Self::Bar(3));
+        x
+    }
+
+    fn baz() -> Self {
+        let x = Self::Baz { i: 42 };
+        check_pat!(x, Self::Baz { i: 42 });
+        x
+    }
+
+    fn qux() -> Self {
+        let x = Self::Qux;
+        assert_eq!(x, <Self>::Qux);
+        check_pat!(x, Self::Qux);
+        check_pat!(x, <Self>::Qux);
+        x
+    }
+}
+
+fn main() {
+    let bar = Foo::Bar(1);
+    assert_eq!(bar, FooAlias::Bar(1));
+    assert_eq!(bar, <FooAlias>::Bar(1));
+    check_pat!(bar, FooAlias::Bar(1));
+
+    let baz = FooAlias::Baz { i: 2 };
+    assert_eq!(baz, Foo::Baz { i: 2 });
+    check_pat!(baz, FooAlias::Baz { i: 2 });
+
+    let qux = Foo::Qux;
+    assert_eq!(qux, FooAlias::Qux);
+    assert_eq!(qux, <FooAlias>::Qux);
+    check_pat!(qux, FooAlias::Qux);
+    check_pat!(qux, <FooAlias>::Qux);
+
+    assert_eq!(Foo::bar(), Foo::Bar(3));
+    assert_eq!(Foo::baz(), Foo::Baz { i: 42 });
+    assert_eq!(Foo::qux(), Foo::Qux);
+
+    let some = Option::Some(4);
+    assert_eq!(some, OptionAlias::Some(4));
+    check_pat!(some, OptionAlias::Some(4));
+}
diff --git a/src/test/ui/type/type-alias-bounds.rs b/src/test/ui/type/type-alias-bounds.rs
index f3cc5becc6f..06705a2ebf5 100644
--- a/src/test/ui/type/type-alias-bounds.rs
+++ b/src/test/ui/type/type-alias-bounds.rs
@@ -1,6 +1,6 @@
 // Test `ignored_generic_bounds` lint warning about bounds in type aliases.
 
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![allow(dead_code)]
 
 use std::rc::Rc;
diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
index 9eed80ad886..710b7c9bbee 100644
--- a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
+++ b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // rust-lang/rust#55810: types for a binding in a match arm can be
 // inferred from arms that come later in the match.
diff --git a/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
index 9fe8a5c832c..f476704cd8a 100644
--- a/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
+++ b/src/test/ui/uninhabited/privately-uninhabited-dead-code.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![deny(unused_variables)]
 
diff --git a/src/test/ui/union/union-const-eval.rs b/src/test/ui/union/union-const-eval.rs
index 05e849a3bb6..90af8de447d 100644
--- a/src/test/ui/union/union-const-eval.rs
+++ b/src/test/ui/union/union-const-eval.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(const_fn_union)]
 
 union U {
diff --git a/src/test/ui/unreachable/unreachable-try-pattern.rs b/src/test/ui/unreachable/unreachable-try-pattern.rs
index 6665c58e457..cbc5fcee2f0 100644
--- a/src/test/ui/unreachable/unreachable-try-pattern.rs
+++ b/src/test/ui/unreachable/unreachable-try-pattern.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 #![feature(never_type, exhaustive_patterns)]
 #![warn(unreachable_code)]
 #![warn(unreachable_patterns)]
diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/unrestricted-attribute-tokens.rs
index b07ab96bce1..e31bc91a00a 100644
--- a/src/test/ui/unrestricted-attribute-tokens.rs
+++ b/src/test/ui/unrestricted-attribute-tokens.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/unsized-locals/unsized-index.rs b/src/test/ui/unsized-locals/unsized-index.rs
index 2e6bd82bda3..19ad97a853e 100644
--- a/src/test/ui/unsized-locals/unsized-index.rs
+++ b/src/test/ui/unsized-locals/unsized-index.rs
@@ -1,4 +1,4 @@
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 // `std::ops::Index` has an `: ?Sized` bound on the `Idx` type param. This is
 // an accidental left-over from the times when it `Index` was by-reference.
diff --git a/src/test/ui/user-defined-macro-rules.rs b/src/test/ui/user-defined-macro-rules.rs
index 31bfdd025d9..09e071ec454 100644
--- a/src/test/ui/user-defined-macro-rules.rs
+++ b/src/test/ui/user-defined-macro-rules.rs
@@ -1,5 +1,9 @@
-#![allow(unused_macros)]
+// check-pass
 
-macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+macro_rules! macro_rules { () => { struct S; } } // OK
 
-fn main() {}
+macro_rules! {} // OK, calls the macro defined above
+
+fn main() {
+    let s = S;
+}
diff --git a/src/test/ui/user-defined-macro-rules.stderr b/src/test/ui/user-defined-macro-rules.stderr
deleted file mode 100644
index 057515228e0..00000000000
--- a/src/test/ui/user-defined-macro-rules.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: user-defined macros may not be named `macro_rules`
-  --> $DIR/user-defined-macro-rules.rs:3:1
-   |
-LL | macro_rules! macro_rules { () => {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/variance/variance-use-contravariant-struct-2.rs b/src/test/ui/variance/variance-use-contravariant-struct-2.rs
index 77bd2b79f8c..2113eb2addb 100644
--- a/src/test/ui/variance/variance-use-contravariant-struct-2.rs
+++ b/src/test/ui/variance/variance-use-contravariant-struct-2.rs
@@ -2,7 +2,7 @@
 // they permit lifetimes to be approximated as expected.
 
 #![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct SomeStruct<T>(fn(T));
 
diff --git a/src/test/ui/variance/variance-use-covariant-struct-2.rs b/src/test/ui/variance/variance-use-covariant-struct-2.rs
index cb8159d8a68..ecd2204c991 100644
--- a/src/test/ui/variance/variance-use-covariant-struct-2.rs
+++ b/src/test/ui/variance/variance-use-covariant-struct-2.rs
@@ -2,7 +2,7 @@
 // be shortened.
 
 #![allow(dead_code)]
-// compile-pass
+// build-pass (FIXME(62277): could be check-pass?)
 
 struct SomeStruct<T>(T);
 
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 722979c3c14..a75d9f0b0bb 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -99,6 +99,36 @@ impl fmt::Display for Mode {
     }
 }
 
+#[derive(Clone, Copy, PartialEq, Debug, Hash)]
+pub enum PassMode {
+    Check,
+    Build,
+    Run,
+}
+
+impl FromStr for PassMode {
+    type Err = ();
+    fn from_str(s: &str) -> Result<Self, ()> {
+        match s {
+            "check" => Ok(PassMode::Check),
+            "build" => Ok(PassMode::Build),
+            "run" => Ok(PassMode::Run),
+            _ => Err(()),
+        }
+    }
+}
+
+impl fmt::Display for PassMode {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let s = match *self {
+            PassMode::Check => "check",
+            PassMode::Build => "build",
+            PassMode::Run => "run",
+        };
+        fmt::Display::fmt(s, f)
+    }
+}
+
 #[derive(Clone, Debug, PartialEq)]
 pub enum CompareMode {
     Nll,
@@ -184,6 +214,9 @@ pub struct Config {
     /// Exactly match the filter, rather than a substring
     pub filter_exact: bool,
 
+    /// Force the pass mode of a check/build/run-pass test to this mode.
+    pub force_pass_mode: Option<PassMode>,
+
     /// Write out a parseable log of tests that were run
     pub logfile: Option<PathBuf>,
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 6ce7461f759..52f777db2da 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
 
 use log::*;
 
-use crate::common::{self, CompareMode, Config, Mode};
+use crate::common::{self, CompareMode, Config, Mode, PassMode};
 use crate::util;
 
 use crate::extract_gdb_version;
@@ -290,13 +290,6 @@ impl EarlyProps {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub enum PassMode {
-    Check,
-    Build,
-    Run,
-}
-
 #[derive(Clone, Debug)]
 pub struct TestProps {
     // Lines that should be expected, in order, on standard out
@@ -357,7 +350,9 @@ pub struct TestProps {
     // arguments. (In particular, it propagates to the aux-builds.)
     pub incremental_dir: Option<PathBuf>,
     // How far should the test proceed while still passing.
-    pub pass_mode: Option<PassMode>,
+    pass_mode: Option<PassMode>,
+    // Ignore `--pass` overrides from the command line for this test.
+    ignore_pass: bool,
     // rustdoc will test the output of the `--test` option
     pub check_test_line_numbers_match: bool,
     // Do not pass `-Z ui-testing` to UI tests
@@ -400,6 +395,7 @@ impl TestProps {
             forbid_output: vec![],
             incremental_dir: None,
             pass_mode: None,
+            ignore_pass: false,
             check_test_line_numbers_match: false,
             disable_ui_testing_normalization: false,
             normalize_stdout: vec![],
@@ -528,6 +524,10 @@ impl TestProps {
 
             self.update_pass_mode(ln, cfg, config);
 
+            if !self.ignore_pass {
+                self.ignore_pass = config.parse_ignore_pass(ln);
+            }
+
             if !self.disable_ui_testing_normalization {
                 self.disable_ui_testing_normalization =
                     config.parse_disable_ui_testing_normalization(ln);
@@ -608,6 +608,15 @@ impl TestProps {
             (_, None) => {}
         }
     }
+
+    pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
+        if !self.ignore_pass {
+            if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
+                return mode;
+            }
+        }
+        self.pass_mode
+    }
 }
 
 fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
@@ -743,6 +752,10 @@ impl Config {
         self.parse_name_directive(line, "check-test-line-numbers-match")
     }
 
+    fn parse_ignore_pass(&self, line: &str) -> bool {
+        self.parse_name_directive(line, "ignore-pass")
+    }
+
     fn parse_assembly_output(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "assembly-output")
             .map(|r| r.trim().to_string())
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index d0dc9d11d39..597fdf2d95e 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -5,7 +5,7 @@
 
 extern crate test;
 
-use crate::common::CompareMode;
+use crate::common::{CompareMode, PassMode};
 use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
 use crate::common::{Config, TestPaths};
 use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
@@ -128,6 +128,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "(compile-fail|run-fail|run-pass|\
              run-pass-valgrind|pretty|debug-info|incremental|mir-opt)",
         )
+        .optopt(
+            "",
+            "pass",
+            "force {check,build,run}-pass tests to this mode.",
+            "check | build | run"
+        )
         .optflag("", "ignored", "run tests marked as ignored")
         .optflag("", "exact", "filters match exactly")
         .optopt(
@@ -320,6 +326,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
         run_ignored,
         filter: matches.free.first().cloned(),
         filter_exact: matches.opt_present("exact"),
+        force_pass_mode: matches.opt_str("pass").map(|mode|
+            mode.parse::<PassMode>()
+                .unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
+        ),
         logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
         runtool: matches.opt_str("runtool"),
         host_rustcflags: matches.opt_str("host-rustcflags"),
@@ -382,6 +392,10 @@ pub fn log_config(config: &Config) {
         ),
     );
     logv(c, format!("filter_exact: {}", config.filter_exact));
+    logv(c, format!(
+        "force_pass_mode: {}",
+        opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),
+    ));
     logv(c, format!("runtool: {}", opt_str(&config.runtool)));
     logv(
         c,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 8b52a529d44..35caf82dd71 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,6 +1,6 @@
 // ignore-tidy-filelength
 
-use crate::common::CompareMode;
+use crate::common::{CompareMode, PassMode};
 use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
 use crate::common::{output_base_dir, output_base_name, output_testname_unique};
 use crate::common::{Codegen, CodegenUnits, Rustdoc};
@@ -10,7 +10,7 @@ use crate::common::{Config, TestPaths};
 use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly};
 use diff;
 use crate::errors::{self, Error, ErrorKind};
-use crate::header::{TestProps, PassMode};
+use crate::header::TestProps;
 use crate::json;
 use regex::{Captures, Regex};
 use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
@@ -260,6 +260,10 @@ pub fn compute_stamp_hash(config: &Config) -> String {
         env::var_os("PYTHONPATH").hash(&mut hash);
     }
 
+    if let Ui | RunPass | Incremental | Pretty = config.mode {
+        config.force_pass_mode.hash(&mut hash);
+    }
+
     format!("{:x}", hash.finish())
 }
 
@@ -309,10 +313,13 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn pass_mode(&self) -> Option<PassMode> {
+        self.props.pass_mode(self.config)
+    }
+
     fn should_run_successfully(&self) -> bool {
         match self.config.mode {
-            RunPass => true,
-            Ui => self.props.pass_mode == Some(PassMode::Run),
+            RunPass | Ui => self.pass_mode() == Some(PassMode::Run),
             mode => panic!("unimplemented for mode {:?}", mode),
         }
     }
@@ -322,7 +329,7 @@ impl<'test> TestCx<'test> {
             CompileFail => false,
             RunPass => true,
             JsDocTest => true,
-            Ui => self.props.pass_mode.is_some(),
+            Ui => self.pass_mode().is_some(),
             Incremental => {
                 let revision = self.revision
                     .expect("incremental tests require a list of revisions");
@@ -330,7 +337,7 @@ impl<'test> TestCx<'test> {
                     true
                 } else if revision.starts_with("cfail") {
                     // FIXME: would be nice if incremental revs could start with "cpass"
-                    self.props.pass_mode.is_some()
+                    self.pass_mode().is_some()
                 } else {
                     panic!("revision name must begin with rpass, rfail, or cfail");
                 }
@@ -1341,7 +1348,7 @@ impl<'test> TestCx<'test> {
     fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
         debug!("check_error_patterns");
         if self.props.error_patterns.is_empty() {
-            if self.props.pass_mode.is_some() {
+            if self.pass_mode().is_some() {
                 return;
             } else {
                 self.fatal(&format!(
@@ -1871,7 +1878,11 @@ impl<'test> TestCx<'test> {
         result
     }
 
-    fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
+    fn make_compile_args(
+        &self,
+        input_file: &Path,
+        output_file: TargetLocation,
+    ) -> Command {
         let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") ||
                          self.config.src_base.ends_with("rustdoc-js");
         let mut rustc = if !is_rustdoc {
@@ -1968,14 +1979,7 @@ impl<'test> TestCx<'test> {
             }
         }
 
-        if self.props.pass_mode == Some(PassMode::Check) {
-            assert!(
-                !self
-                    .props
-                    .compile_flags
-                    .iter()
-                    .any(|s| s.starts_with("--emit"))
-            );
+        if let Some(PassMode::Check) = self.pass_mode() {
             rustc.args(&["--emit", "metadata"]);
         }
 
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 945f007c0d305c3ec069b5e5d911ef783f6d70e
+Subproject d2df509867fbbbd35730c90aef54a8e73b046cd
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 9e7c18b7f56..d5dff1dcae0 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -72,32 +72,33 @@ def issue(
 ):
     # Open an issue about the toolstate failure.
     assignees = [x.strip() for x in maintainers.split('@') if x != '']
-    assignees.append(relevant_pr_user)
     if status == 'test-fail':
         status_description = 'has failing tests'
     else:
         status_description = 'no longer builds'
+    request = json.dumps({
+        'body': maybe_delink(textwrap.dedent('''\
+        Hello, this is your friendly neighborhood mergebot.
+        After merging PR {}, I observed that the tool {} {}.
+        A follow-up PR to the repository {} is needed to fix the fallout.
+
+        cc @{}, do you think you would have time to do the follow-up work?
+        If so, that would be great!
+
+        cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
+
+        ''').format(
+            relevant_pr_number, tool, status_description,
+            REPOS.get(tool), relevant_pr_user, pr_reviewer
+        )),
+        'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
+        'assignees': assignees,
+        'labels': ['T-compiler', 'I-nominated'],
+    })
+    print("Creating issue:\n{}".format(request))
     response = urllib2.urlopen(urllib2.Request(
         gh_url(),
-        json.dumps({
-            'body': maybe_delink(textwrap.dedent('''\
-            Hello, this is your friendly neighborhood mergebot.
-            After merging PR {}, I observed that the tool {} {}.
-            A follow-up PR to the repository {} is needed to fix the fallout.
-
-            cc @{}, do you think you would have time to do the follow-up work?
-            If so, that would be great!
-
-            cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
-
-            ''').format(
-                relevant_pr_number, tool, status_description,
-                REPOS.get(tool), relevant_pr_user, pr_reviewer
-            )),
-            'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
-            'assignees': assignees,
-            'labels': ['T-compiler', 'I-nominated'],
-        }),
+        request,
         {
             'Authorization': 'token ' + github_token,
             'Content-Type': 'application/json',
@@ -135,13 +136,13 @@ def update_latest(
         for status in latest:
             tool = status['tool']
             changed = False
-            create_issue = False
+            create_issue_for_status = None # set to the status that caused the issue
 
             for os, s in current_status.items():
                 old = status[os]
                 new = s.get(tool, old)
                 status[os] = new
-                if new > old:
+                if new > old: # comparing the strings, but they are ordered appropriately!
                     # things got fixed or at least the status quo improved
                     changed = True
                     message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
@@ -156,20 +157,24 @@ def update_latest(
                     # Most tools only create issues for build failures.
                     # Other failures can be spurious.
                     if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
-                        create_issue = True
+                        create_issue_for_status = new
 
-            if create_issue:
+            if create_issue_for_status is not None:
                 try:
                     issue(
-                        tool, new, MAINTAINERS.get(tool, ''),
+                        tool, create_issue_for_status, MAINTAINERS.get(tool, ''),
                         relevant_pr_number, relevant_pr_user, pr_reviewer,
                     )
-                except IOError as e:
+                except urllib2.HTTPError as e:
                     # network errors will simply end up not creating an issue, but that's better
                     # than failing the entire build job
-                    print("I/O error: {0}".format(e))
+                    print("HTTPError when creating issue for status regression: {0}\n{1}"
+                          .format(e, e.read()))
+                except IOError as e:
+                    print("I/O error when creating issue for status regression: {0}".format(e))
                 except:
-                    print("Unexpected error: {0}".format(sys.exc_info()[0]))
+                    print("Unexpected error when creating issue for status regression: {0}"
+                          .format(sys.exc_info()[0]))
                     raise
 
             if changed:
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 597c9be8c75be3e664f189c4325c96cf9b464dc
+Subproject 124483dd2f10fe3ba32f7f5b75f32224c77f901