about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/doc/not_found.md14
-rw-r--r--src/libcore/cell.rs6
-rw-r--r--src/libcore/iter/mod.rs18
-rw-r--r--src/libcore/macros.rs2
-rw-r--r--src/libcore/option.rs17
-rw-r--r--src/libcore/result.rs10
-rw-r--r--src/librustc/diagnostics.rs8
-rw-r--r--src/librustc/ich/hcx.rs65
-rw-r--r--src/librustc/ich/impls_hir.rs106
-rw-r--r--src/librustc/ich/impls_mir.rs57
-rw-r--r--src/librustc/ich/impls_ty.rs10
-rw-r--r--src/librustc/infer/mod.rs49
-rw-r--r--src/librustc/mir/mod.rs69
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/traits/project.rs17
-rw-r--r--src/librustc/traits/select.rs3
-rw-r--r--src/librustc/ty/instance.rs4
-rw-r--r--src/librustc/ty/maps/config.rs78
-rw-r--r--src/librustc/ty/maps/mod.rs6
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs10
-rw-r--r--src/librustc/ty/maps/plumbing.rs3
-rw-r--r--src/librustc/ty/sty.rs44
-rw-r--r--src/librustc_driver/driver.rs2
-rw-r--r--src/librustc_errors/styled_buffer.rs17
-rw-r--r--src/librustc_metadata/astencode.rs4
-rw-r--r--src/librustc_metadata/decoder.rs34
-rw-r--r--src/librustc_mir/borrow_check/mod.rs542
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs147
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/annotation.rs48
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs100
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs71
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs305
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs66
-rw-r--r--src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/universal_regions.rs704
-rw-r--r--src/librustc_mir/build/cfg.rs11
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs60
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs92
-rw-r--r--src/librustc_mir/dataflow/mod.rs30
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs23
-rw-r--r--src/librustc_mir/transform/type_check.rs83
-rw-r--r--src/librustc_mir/util/pretty.rs140
-rw-r--r--src/librustc_passes/ast_validation.rs16
-rw-r--r--src/librustc_trans/common.rs4
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs5
-rw-r--r--src/librustc_trans_utils/monomorphize.rs4
-rw-r--r--src/librustc_typeck/check/callee.rs3
-rw-r--r--src/librustc_typeck/check/coercion.rs3
-rw-r--r--src/librustc_typeck/collect.rs26
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/html/layout.rs1
-rw-r--r--src/librustdoc/html/render.rs31
-rw-r--r--src/librustdoc/html/static/main.js55
-rw-r--r--src/librustdoc/html/static/rustdoc.css73
-rw-r--r--src/librustdoc/html/static/styles/main.css89
-rw-r--r--src/librustdoc/markdown.rs47
-rw-r--r--src/libstd/fs.rs134
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/macros.rs2
-rw-r--r--src/libsyntax/feature_gate.rs18
-rw-r--r--src/libsyntax/parse/lexer/mod.rs14
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/libsyntax_pos/lib.rs15
-rw-r--r--src/libsyntax_pos/symbol.rs21
-rw-r--r--src/rustllvm/PassWrapper.cpp2
-rw-r--r--src/test/codegen/abi-sysv64.rs1
-rw-r--r--src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs6
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs10
-rw-r--r--src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs1
-rw-r--r--src/test/compile-fail/borrowck/borrowck-union-borrow.rs13
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs3
-rw-r--r--src/test/compile-fail/issue-10412.rs (renamed from src/test/parse-fail/issue-10412.rs)6
-rw-r--r--src/test/compile-fail/issue-25579.rs6
-rw-r--r--src/test/compile-fail/issue-46311.rs (renamed from src/test/compile-fail/no-core-gated.rs)11
-rw-r--r--src/test/compile-fail/lifetime-no-keyword.rs (renamed from src/test/parse-fail/lifetime-no-keyword.rs)9
-rw-r--r--src/test/compile-fail/region-borrow-params-issue-29793-big.rs10
-rw-r--r--src/test/compile-fail/regions-static-bound.rs16
-rw-r--r--src/test/incremental/hashes/call_expressions.rs2
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs62
-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.rs112
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs236
-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.rs62
-rw-r--r--src/test/incremental/hashes/let_expressions.rs2
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs82
-rw-r--r--src/test/incremental/hashes/match_expressions.rs2
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs165
-rw-r--r--src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs225
-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.rs92
-rw-r--r--src/test/incremental/hashes/while_loops.rs92
-rw-r--r--src/test/incremental/ich_method_call_trait_scope.rs15
-rw-r--r--src/test/incremental/ich_nested_items.rs13
-rw-r--r--src/test/incremental/ich_resolve_results.rs40
-rw-r--r--src/test/incremental/source_loc_macros.rs30
-rw-r--r--src/test/incremental/spans_insignificant_w_o_debuginfo.rs26
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs3
-rw-r--r--src/test/mir-opt/nll/liveness-call-subtlety.rs8
-rw-r--r--src/test/mir-opt/nll/liveness-drop-intra-block.rs10
-rw-r--r--src/test/mir-opt/nll/liveness-interblock.rs8
-rw-r--r--src/test/mir-opt/nll/named-lifetimes-basic.rs17
-rw-r--r--src/test/mir-opt/nll/reborrow-basic.rs7
-rw-r--r--src/test/mir-opt/nll/region-liveness-basic.rs14
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs2
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs2
-rw-r--r--src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs6
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs6
-rw-r--r--src/test/parse-fail/issue-17383.rs2
-rw-r--r--src/test/parse-fail/tag-variant-disr-non-nullary.rs2
-rw-r--r--src/test/run-pass/abi-sysv64-arg-passing.rs1
-rw-r--r--src/test/run-pass/abi-sysv64-register-usage.rs1
-rw-r--r--src/test/run-pass/auxiliary/svh-a-comment.rs36
-rw-r--r--src/test/run-pass/auxiliary/svh-a-doc.rs38
-rw-r--r--src/test/run-pass/auxiliary/svh-a-macro.rs37
-rw-r--r--src/test/run-pass/auxiliary/svh-a-no-change.rs35
-rw-r--r--src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs37
-rw-r--r--src/test/run-pass/auxiliary/svh-a-whitespace.rs37
-rw-r--r--src/test/run-pass/hygiene/issue-44128.rs25
-rw-r--r--src/test/run-pass/issue-44373.rs2
-rw-r--r--src/test/run-pass/match-pipe-binding.rs1
-rw-r--r--src/test/run-pass/svh-add-doc.rs23
-rw-r--r--src/test/run-pass/svh-add-macro.rs23
-rw-r--r--src/test/run-pass/svh-add-nothing.rs2
-rw-r--r--src/test/run-pass/svh-add-redundant-cfg.rs23
-rw-r--r--src/test/run-pass/svh-add-whitespace.rs23
-rw-r--r--src/test/run-pass/thinlto/weak-works.rs (renamed from src/test/run-pass/svh-add-comment.rs)32
-rw-r--r--src/test/ui/auxiliary/cfg-target-thread-local.rs (renamed from src/test/compile-fail/auxiliary/cfg-target-thread-local.rs)0
-rw-r--r--src/test/ui/codemap_tests/tab.stderr8
-rw-r--r--src/test/ui/codemap_tests/tab_2.stderr4
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr10
-rw-r--r--src/test/ui/feature-gate-abi-msp430-interrupt.rs (renamed from src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs)0
-rw-r--r--src/test/ui/feature-gate-abi-msp430-interrupt.stderr10
-rw-r--r--src/test/ui/feature-gate-abi.rs (renamed from src/test/compile-fail/feature-gate-abi.rs)0
-rw-r--r--src/test/ui/feature-gate-abi.stderr450
-rw-r--r--src/test/ui/feature-gate-abi_unadjusted.rs (renamed from src/test/compile-fail/unadjusted-unstable.rs)2
-rw-r--r--src/test/ui/feature-gate-abi_unadjusted.stderr12
-rw-r--r--src/test/ui/feature-gate-advanced-slice-features.rs (renamed from src/test/compile-fail/feature-gate-advanced-slice-features.rs)0
-rw-r--r--src/test/ui/feature-gate-advanced-slice-features.stderr18
-rw-r--r--src/test/ui/feature-gate-allocator_internals.rs (renamed from src/test/compile-fail/feature-gate-allocator_internals.rs)0
-rw-r--r--src/test/ui/feature-gate-allocator_internals.stderr10
-rw-r--r--src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.rs (renamed from src/test/compile-fail/feature-gate-allow-internal-unsafe-nested-macro.rs)0
-rw-r--r--src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr13
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable-nested-macro.rs (renamed from src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs)0
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr13
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable-struct.rs (renamed from src/test/compile-fail/feature-gate-allow-internal-unstable-struct.rs)0
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable-struct.stderr10
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable.rs (renamed from src/test/compile-fail/feature-gate-allow-internal-unstable.rs)0
-rw-r--r--src/test/ui/feature-gate-allow-internal-unstable.stderr10
-rw-r--r--src/test/ui/feature-gate-allow_fail.rs (renamed from src/test/compile-fail/feature-gate-allow_fail.rs)0
-rw-r--r--src/test/ui/feature-gate-allow_fail.stderr10
-rw-r--r--src/test/ui/feature-gate-arbitrary-self-types.rs (renamed from src/test/compile-fail/feature-gate-arbitrary-self-types.rs)0
-rw-r--r--src/test/ui/feature-gate-arbitrary-self-types.stderr29
-rw-r--r--src/test/ui/feature-gate-asm.rs (renamed from src/test/compile-fail/asm-gated.rs)2
-rw-r--r--src/test/ui/feature-gate-asm.stderr10
-rw-r--r--src/test/ui/feature-gate-asm2.rs (renamed from src/test/compile-fail/asm-gated2.rs)0
-rw-r--r--src/test/ui/feature-gate-asm2.stderr10
-rw-r--r--src/test/ui/feature-gate-assoc-type-defaults.rs (renamed from src/test/compile-fail/feature-gate-assoc-type-defaults.rs)0
-rw-r--r--src/test/ui/feature-gate-assoc-type-defaults.stderr10
-rw-r--r--src/test/ui/feature-gate-box-expr.rs (renamed from src/test/compile-fail/feature-gate-box-expr.rs)0
-rw-r--r--src/test/ui/feature-gate-box-expr.stderr10
-rw-r--r--src/test/ui/feature-gate-box_patterns.rs (renamed from src/test/compile-fail/feature-gate-box-pat.rs)2
-rw-r--r--src/test/ui/feature-gate-box_patterns.stderr10
-rw-r--r--src/test/ui/feature-gate-box_syntax.rs (renamed from src/test/compile-fail/gated-box-syntax.rs)2
-rw-r--r--src/test/ui/feature-gate-box_syntax.stderr10
-rw-r--r--src/test/ui/feature-gate-catch_expr.rs (renamed from src/test/compile-fail/feature-gate-catch_expr.rs)0
-rw-r--r--src/test/ui/feature-gate-catch_expr.stderr14
-rw-r--r--src/test/ui/feature-gate-cfg-target-feature.rs (renamed from src/test/compile-fail/feature-gate-cfg-target-feature.rs)0
-rw-r--r--src/test/ui/feature-gate-cfg-target-feature.stderr34
-rw-r--r--src/test/ui/feature-gate-cfg-target-has-atomic.rs (renamed from src/test/compile-fail/feature-gate-cfg-target-has-atomic.rs)0
-rw-r--r--src/test/ui/feature-gate-cfg-target-has-atomic.stderr122
-rw-r--r--src/test/ui/feature-gate-cfg-target-thread-local.rs (renamed from src/test/compile-fail/feature-gate-cfg-target-thread-local.rs)0
-rw-r--r--src/test/ui/feature-gate-cfg-target-thread-local.stderr10
-rw-r--r--src/test/ui/feature-gate-cfg-target-vendor.rs (renamed from src/test/compile-fail/feature-gate-cfg-target-vendor.rs)0
-rw-r--r--src/test/ui/feature-gate-cfg-target-vendor.stderr34
-rw-r--r--src/test/ui/feature-gate-clone-closures.rs (renamed from src/test/compile-fail/feature-gate-clone-closures.rs)0
-rw-r--r--src/test/ui/feature-gate-clone-closures.stderr10
-rw-r--r--src/test/ui/feature-gate-compiler-builtins.rs (renamed from src/test/compile-fail/feature-gate-compiler-builtins.rs)0
-rw-r--r--src/test/ui/feature-gate-compiler-builtins.stderr10
-rw-r--r--src/test/ui/feature-gate-concat_idents.rs (renamed from src/test/compile-fail/concat_idents-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-concat_idents.stderr18
-rw-r--r--src/test/ui/feature-gate-concat_idents2.rs (renamed from src/test/compile-fail/gated-concat_idents.rs)0
-rw-r--r--src/test/ui/feature-gate-concat_idents2.stderr10
-rw-r--r--src/test/ui/feature-gate-concat_idents3.rs (renamed from src/test/compile-fail/concat_idents-gate2.rs)0
-rw-r--r--src/test/ui/feature-gate-concat_idents3.stderr18
-rw-r--r--src/test/ui/feature-gate-conservative_impl_trait.rs (renamed from src/test/compile-fail/impl-trait/feature-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-conservative_impl_trait.stderr10
-rw-r--r--src/test/ui/feature-gate-const-indexing.rs (renamed from src/test/compile-fail/feature-gate-const-indexing.rs)0
-rw-r--r--src/test/ui/feature-gate-const-indexing.stderr8
-rw-r--r--src/test/ui/feature-gate-const_fn.rs (renamed from src/test/compile-fail/const-fn-stability.rs)2
-rw-r--r--src/test/ui/feature-gate-const_fn.stderr60
-rw-r--r--src/test/ui/feature-gate-copy-closures.rs (renamed from src/test/compile-fail/feature-gate-copy-closures.rs)0
-rw-r--r--src/test/ui/feature-gate-copy-closures.stderr12
-rw-r--r--src/test/ui/feature-gate-crate_in_paths.rs (renamed from src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs)0
-rw-r--r--src/test/ui/feature-gate-crate_in_paths.stderr10
-rw-r--r--src/test/ui/feature-gate-crate_visibility_modifier.rs (renamed from src/test/compile-fail/feature-gate-crate_visibility_modifier.rs)0
-rw-r--r--src/test/ui/feature-gate-crate_visibility_modifier.stderr10
-rw-r--r--src/test/ui/feature-gate-custom_attribute.rs (renamed from src/test/compile-fail/attr-literals.rs)2
-rw-r--r--src/test/ui/feature-gate-custom_attribute.stderr106
-rw-r--r--src/test/ui/feature-gate-custom_attribute2.rs (renamed from src/test/compile-fail/attr-on-generic-formals-are-visited.rs)0
-rw-r--r--src/test/ui/feature-gate-custom_attribute2.stderr138
-rw-r--r--src/test/ui/feature-gate-custom_derive.rs (renamed from src/test/compile-fail/single-derive-attr.rs)2
-rw-r--r--src/test/ui/feature-gate-custom_derive.stderr10
-rw-r--r--src/test/ui/feature-gate-decl_macro.rs (renamed from src/test/compile-fail/feature-gate-decl_macro.rs)0
-rw-r--r--src/test/ui/feature-gate-decl_macro.stderr10
-rw-r--r--src/test/ui/feature-gate-default_type_parameter_fallback.rs (renamed from src/test/compile-fail/type-parameter-invalid-lint.rs)2
-rw-r--r--src/test/ui/feature-gate-default_type_parameter_fallback.stderr21
-rw-r--r--src/test/ui/feature-gate-doc_cfg.rs (renamed from src/test/compile-fail/feature-gate-doc_cfg.rs)0
-rw-r--r--src/test/ui/feature-gate-doc_cfg.stderr10
-rw-r--r--src/test/ui/feature-gate-doc_masked.rs (renamed from src/test/compile-fail/feature-gate-doc_masked.rs)0
-rw-r--r--src/test/ui/feature-gate-doc_masked.stderr10
-rw-r--r--src/test/ui/feature-gate-doc_spotlight.rs (renamed from src/test/compile-fail/feature-gate-doc_spotlight.rs)0
-rw-r--r--src/test/ui/feature-gate-doc_spotlight.stderr10
-rw-r--r--src/test/ui/feature-gate-dotdoteq_in_patterns.rs (renamed from src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs)0
-rw-r--r--src/test/ui/feature-gate-dotdoteq_in_patterns.stderr10
-rw-r--r--src/test/ui/feature-gate-dropck-ugeh-2.rs (renamed from src/test/compile-fail/feature-gate-dropck-ugeh-2.rs)0
-rw-r--r--src/test/ui/feature-gate-dropck-ugeh-2.stderr14
-rw-r--r--src/test/ui/feature-gate-dropck-ugeh.rs (renamed from src/test/compile-fail/feature-gate-dropck-ugeh.rs)0
-rw-r--r--src/test/ui/feature-gate-dropck-ugeh.stderr10
-rw-r--r--src/test/ui/feature-gate-dyn-trait.rs (renamed from src/test/compile-fail/feature-gate-dyn-trait.rs)0
-rw-r--r--src/test/ui/feature-gate-dyn-trait.stderr10
-rw-r--r--src/test/ui/feature-gate-exclusive-range-pattern.rs (renamed from src/test/compile-fail/feature-gate-exclusive-range-pattern.rs)0
-rw-r--r--src/test/ui/feature-gate-exclusive-range-pattern.stderr10
-rw-r--r--src/test/ui/feature-gate-extern_types.rs (renamed from src/test/compile-fail/feature-gate-extern_types.rs)0
-rw-r--r--src/test/ui/feature-gate-extern_types.stderr10
-rw-r--r--src/test/ui/feature-gate-external_doc.rs (renamed from src/test/compile-fail/feature-gate-external_doc.rs)0
-rw-r--r--src/test/ui/feature-gate-external_doc.stderr10
-rw-r--r--src/test/ui/feature-gate-feature-gate.rs (renamed from src/test/compile-fail/feature-gate-feature-gate.rs)0
-rw-r--r--src/test/ui/feature-gate-feature-gate.stderr14
-rw-r--r--src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs (renamed from src/test/compile-fail/feature-gate-fn_must_use-cap-lints-allow.rs)0
-rw-r--r--src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr6
-rw-r--r--src/test/ui/feature-gate-fn_must_use.rs (renamed from src/test/compile-fail/feature-gate-fn_must_use.rs)0
-rw-r--r--src/test/ui/feature-gate-fn_must_use.stderr22
-rw-r--r--src/test/ui/feature-gate-fundamental.rs (renamed from src/test/compile-fail/feature-gate-fundamental.rs)0
-rw-r--r--src/test/ui/feature-gate-fundamental.stderr10
-rw-r--r--src/test/ui/feature-gate-generators.rs (renamed from src/test/compile-fail/feature-gate-generators.rs)0
-rw-r--r--src/test/ui/feature-gate-generators.stderr10
-rw-r--r--src/test/ui/feature-gate-generic_associated_types.rs (renamed from src/test/compile-fail/feature-gate-generic_associated_types.rs)0
-rw-r--r--src/test/ui/feature-gate-generic_associated_types.stderr34
-rw-r--r--src/test/ui/feature-gate-generic_param_attrs.rs (renamed from src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-generic_param_attrs.stderr138
-rw-r--r--src/test/ui/feature-gate-global_allocator.rs (renamed from src/test/compile-fail/feature-gate-global_allocator.rs)0
-rw-r--r--src/test/ui/feature-gate-global_allocator.stderr10
-rw-r--r--src/test/ui/feature-gate-global_asm.rs (renamed from src/test/compile-fail/feature-gate-global_asm.rs)0
-rw-r--r--src/test/ui/feature-gate-global_asm.stderr10
-rw-r--r--src/test/ui/feature-gate-i128_type.rs (renamed from src/test/compile-fail/i128-feature.rs)2
-rw-r--r--src/test/ui/feature-gate-i128_type.stderr18
-rw-r--r--src/test/ui/feature-gate-i128_type2.rs (renamed from src/test/compile-fail/i128-feature-2.rs)0
-rw-r--r--src/test/ui/feature-gate-i128_type2.stderr46
-rw-r--r--src/test/ui/feature-gate-in_band_lifetimes.rs (renamed from src/test/compile-fail/feature-gate-in_band_lifetimes.rs)0
-rw-r--r--src/test/ui/feature-gate-in_band_lifetimes.stderr104
-rw-r--r--src/test/ui/feature-gate-intrinsics.rs (renamed from src/test/compile-fail/feature-gate-intrinsics.rs)0
-rw-r--r--src/test/ui/feature-gate-intrinsics.stderr21
-rw-r--r--src/test/ui/feature-gate-lang-items.rs (renamed from src/test/compile-fail/feature-gate-lang-items.rs)0
-rw-r--r--src/test/ui/feature-gate-lang-items.stderr10
-rw-r--r--src/test/ui/feature-gate-link_args.rs (renamed from src/test/compile-fail/gated-link-args.rs)2
-rw-r--r--src/test/ui/feature-gate-link_args.stderr26
-rw-r--r--src/test/ui/feature-gate-link_cfg.rs (renamed from src/test/compile-fail/link-cfg-gated.rs)2
-rw-r--r--src/test/ui/feature-gate-link_cfg.stderr10
-rw-r--r--src/test/ui/feature-gate-link_llvm_intrinsics.rs (renamed from src/test/compile-fail/gated-link-llvm-intrinsics.rs)2
-rw-r--r--src/test/ui/feature-gate-link_llvm_intrinsics.stderr10
-rw-r--r--src/test/ui/feature-gate-linkage.rs (renamed from src/test/compile-fail/linkage1.rs)2
-rw-r--r--src/test/ui/feature-gate-linkage.stderr10
-rw-r--r--src/test/ui/feature-gate-linker-flavor.rs (renamed from src/test/compile-fail/feature-gate-linker-flavor.rs)0
-rw-r--r--src/test/ui/feature-gate-linker-flavor.stderr10
-rw-r--r--src/test/ui/feature-gate-log_syntax.rs (renamed from src/test/compile-fail/log-syntax-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-log_syntax.stderr10
-rw-r--r--src/test/ui/feature-gate-log_syntax2.rs (renamed from src/test/compile-fail/log-syntax-gate2.rs)0
-rw-r--r--src/test/ui/feature-gate-log_syntax2.stderr10
-rw-r--r--src/test/ui/feature-gate-macro-vis-matcher.rs (renamed from src/test/compile-fail/feature-gate-macro-vis-matcher.rs)0
-rw-r--r--src/test/ui/feature-gate-macro-vis-matcher.stderr10
-rw-r--r--src/test/ui/feature-gate-main.rs (renamed from src/test/compile-fail/feature-gate-main.rs)0
-rw-r--r--src/test/ui/feature-gate-main.stderr10
-rw-r--r--src/test/ui/feature-gate-match_beginning_vert.rs (renamed from src/test/compile-fail/feature-gate-match_beginning_vert.rs)0
-rw-r--r--src/test/ui/feature-gate-match_beginning_vert.stderr26
-rw-r--r--src/test/ui/feature-gate-match_default_bindings.rs (renamed from src/test/compile-fail/feature-gate-match_default_bindings.rs)0
-rw-r--r--src/test/ui/feature-gate-match_default_bindings.stderr10
-rw-r--r--src/test/ui/feature-gate-may-dangle.rs (renamed from src/test/compile-fail/feature-gate-may-dangle.rs)0
-rw-r--r--src/test/ui/feature-gate-may-dangle.stderr10
-rw-r--r--src/test/ui/feature-gate-naked_functions.rs (renamed from src/test/compile-fail/gated-naked_functions.rs)2
-rw-r--r--src/test/ui/feature-gate-naked_functions.stderr18
-rw-r--r--src/test/ui/feature-gate-needs-allocator.rs (renamed from src/test/compile-fail/feature-gate-needs-allocator.rs)0
-rw-r--r--src/test/ui/feature-gate-needs-allocator.stderr10
-rw-r--r--src/test/ui/feature-gate-negate-unsigned.rs (renamed from src/test/compile-fail/feature-gate-negate-unsigned.rs)0
-rw-r--r--src/test/ui/feature-gate-negate-unsigned.stderr14
-rw-r--r--src/test/ui/feature-gate-never_type.rs (renamed from src/test/compile-fail/never-disabled.rs)2
-rw-r--r--src/test/ui/feature-gate-never_type.stderr42
-rw-r--r--src/test/ui/feature-gate-no-debug-2.rs (renamed from src/test/compile-fail/feature-gate-no-debug-2.rs)0
-rw-r--r--src/test/ui/feature-gate-no-debug-2.stderr14
-rw-r--r--src/test/ui/feature-gate-no-debug.rs (renamed from src/test/compile-fail/feature-gate-no-debug.rs)0
-rw-r--r--src/test/ui/feature-gate-no-debug.stderr10
-rw-r--r--src/test/ui/feature-gate-no_core.rs (renamed from src/test/compile-fail/gated-no-core.rs)2
-rw-r--r--src/test/ui/feature-gate-no_core.stderr10
-rw-r--r--src/test/ui/feature-gate-non_ascii_idents.rs (renamed from src/test/compile-fail/gated-non-ascii-idents.rs)2
-rw-r--r--src/test/ui/feature-gate-non_ascii_idents.stderr122
-rw-r--r--src/test/ui/feature-gate-non_exhaustive.rs (renamed from src/test/compile-fail/feature-gate-non_exhaustive.rs)0
-rw-r--r--src/test/ui/feature-gate-non_exhaustive.stderr10
-rw-r--r--src/test/ui/feature-gate-omit-gdb-pretty-printer-section.rs (renamed from src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs)0
-rw-r--r--src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr10
-rw-r--r--src/test/ui/feature-gate-on-unimplemented.rs (renamed from src/test/compile-fail/feature-gate-on-unimplemented.rs)0
-rw-r--r--src/test/ui/feature-gate-on-unimplemented.stderr10
-rw-r--r--src/test/ui/feature-gate-optin-builtin-traits.rs (renamed from src/test/compile-fail/feature-gate-optin-builtin-traits.rs)0
-rw-r--r--src/test/ui/feature-gate-optin-builtin-traits.stderr26
-rw-r--r--src/test/ui/feature-gate-overlapping_marker_traits.rs (renamed from src/test/compile-fail/feature-gate-overlapping_marker_traits.rs)0
-rw-r--r--src/test/ui/feature-gate-overlapping_marker_traits.stderr10
-rw-r--r--src/test/ui/feature-gate-placement-expr.rs (renamed from src/test/compile-fail/feature-gate-placement-expr.rs)0
-rw-r--r--src/test/ui/feature-gate-placement-expr.stderr10
-rw-r--r--src/test/ui/feature-gate-plugin.rs (renamed from src/test/compile-fail/feature-gate-plugin.rs)0
-rw-r--r--src/test/ui/feature-gate-plugin.stderr10
-rw-r--r--src/test/ui/feature-gate-plugin_registrar.rs (renamed from src/test/compile-fail/gated-plugin_registrar.rs)2
-rw-r--r--src/test/ui/feature-gate-plugin_registrar.stderr10
-rw-r--r--src/test/ui/feature-gate-prelude_import.rs (renamed from src/test/compile-fail/feature-gate-prelude_import.rs)0
-rw-r--r--src/test/ui/feature-gate-prelude_import.stderr10
-rw-r--r--src/test/ui/feature-gate-profiler-runtime.rs (renamed from src/test/compile-fail/feature-gate-profiler-runtime.rs)0
-rw-r--r--src/test/ui/feature-gate-profiler-runtime.stderr10
-rw-r--r--src/test/ui/feature-gate-repr-simd.rs (renamed from src/test/compile-fail/feature-gate-repr-simd.rs)0
-rw-r--r--src/test/ui/feature-gate-repr-simd.stderr10
-rw-r--r--src/test/ui/feature-gate-repr128.rs (renamed from src/test/compile-fail/feature-gate-repr128.rs)0
-rw-r--r--src/test/ui/feature-gate-repr128.stderr13
-rw-r--r--src/test/ui/feature-gate-repr_align.rs (renamed from src/test/compile-fail/feature-gate-repr_align.rs)0
-rw-r--r--src/test/ui/feature-gate-repr_align.stderr10
-rw-r--r--src/test/ui/feature-gate-rustc-attrs.rs (renamed from src/test/compile-fail/feature-gate-rustc-attrs.rs)0
-rw-r--r--src/test/ui/feature-gate-rustc-attrs.stderr26
-rw-r--r--src/test/ui/feature-gate-rustc-diagnostic-macros.rs (renamed from src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs)0
-rw-r--r--src/test/ui/feature-gate-rustc-diagnostic-macros.stderr20
-rw-r--r--src/test/ui/feature-gate-rustc_const_unstable.rs (renamed from src/test/compile-fail/feature-gate-rustc_const_unstable.rs)0
-rw-r--r--src/test/ui/feature-gate-rustc_const_unstable.stderr10
-rw-r--r--src/test/ui/feature-gate-sanitizer-runtime.rs (renamed from src/test/compile-fail/feature-gate-sanitizer-runtime.rs)0
-rw-r--r--src/test/ui/feature-gate-sanitizer-runtime.stderr10
-rw-r--r--src/test/ui/feature-gate-simd-ffi.rs (renamed from src/test/compile-fail/feature-gate-simd-ffi.rs)0
-rw-r--r--src/test/ui/feature-gate-simd-ffi.stderr18
-rw-r--r--src/test/ui/feature-gate-simd.rs (renamed from src/test/compile-fail/feature-gate-simd.rs)0
-rw-r--r--src/test/ui/feature-gate-simd.stderr10
-rw-r--r--src/test/ui/feature-gate-slice-patterns.rs (renamed from src/test/compile-fail/feature-gate-slice-patterns.rs)0
-rw-r--r--src/test/ui/feature-gate-slice-patterns.stderr10
-rw-r--r--src/test/ui/feature-gate-staged_api.rs (renamed from src/test/compile-fail/feature-gate-staged_api.rs)0
-rw-r--r--src/test/ui/feature-gate-staged_api.stderr14
-rw-r--r--src/test/ui/feature-gate-start.rs (renamed from src/test/compile-fail/feature-gate-start.rs)0
-rw-r--r--src/test/ui/feature-gate-start.stderr10
-rw-r--r--src/test/ui/feature-gate-static-nobundle.rs (renamed from src/test/compile-fail/feature-gate-static-nobundle.rs)0
-rw-r--r--src/test/ui/feature-gate-static-nobundle.stderr10
-rw-r--r--src/test/ui/feature-gate-stmt_expr_attributes.rs (renamed from src/test/compile-fail/feature-gate-stmt_expr_attributes.rs)0
-rw-r--r--src/test/ui/feature-gate-stmt_expr_attributes.stderr10
-rw-r--r--src/test/ui/feature-gate-target_feature.rs (renamed from src/test/compile-fail/gated-target_feature.rs)2
-rw-r--r--src/test/ui/feature-gate-target_feature.stderr10
-rw-r--r--src/test/ui/feature-gate-thread_local.rs (renamed from src/test/compile-fail/gated-thread-local.rs)2
-rw-r--r--src/test/ui/feature-gate-thread_local.stderr10
-rw-r--r--src/test/ui/feature-gate-trace_macros.rs (renamed from src/test/compile-fail/gated-trace_macros.rs)2
-rw-r--r--src/test/ui/feature-gate-trace_macros.stderr10
-rw-r--r--src/test/ui/feature-gate-type_ascription.rs (renamed from src/test/compile-fail/type-ascription-feature-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-type_ascription.stderr10
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-manual-impls.rs (renamed from src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs)0
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr34
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-method-calls.rs (renamed from src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs)0
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-method-calls.stderr26
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-ufcs-calls.rs (renamed from src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs)0
-rw-r--r--src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr26
-rw-r--r--src/test/ui/feature-gate-unboxed-closures.rs (renamed from src/test/compile-fail/feature-gate-unboxed-closures.rs)0
-rw-r--r--src/test/ui/feature-gate-unboxed-closures.stderr12
-rw-r--r--src/test/ui/feature-gate-underscore-lifetimes.rs (renamed from src/test/compile-fail/feature-gate-underscore-lifetimes.rs)0
-rw-r--r--src/test/ui/feature-gate-underscore-lifetimes.stderr10
-rw-r--r--src/test/ui/feature-gate-universal.rs (renamed from src/test/compile-fail/impl-trait/feature-gate-universal.rs)0
-rw-r--r--src/test/ui/feature-gate-universal.stderr10
-rw-r--r--src/test/ui/feature-gate-unsized_tuple_coercion.rs (renamed from src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs)0
-rw-r--r--src/test/ui/feature-gate-unsized_tuple_coercion.stderr10
-rw-r--r--src/test/ui/feature-gate-untagged_unions.rs (renamed from src/test/compile-fail/union/union-feature-gate.rs)2
-rw-r--r--src/test/ui/feature-gate-untagged_unions.stderr32
-rw-r--r--src/test/ui/feature-gate-unwind-attributes.rs (renamed from src/test/compile-fail/feature-gate-unwind-attributes.rs)0
-rw-r--r--src/test/ui/feature-gate-unwind-attributes.stderr10
-rw-r--r--src/test/ui/feature-gate-use_nested_groups.rs (renamed from src/test/compile-fail/feature-gate-use_nested_groups.rs)0
-rw-r--r--src/test/ui/feature-gate-use_nested_groups.stderr26
-rw-r--r--src/test/ui/feature-gate-used.rs (renamed from src/test/compile-fail/feature-gate-used.rs)0
-rw-r--r--src/test/ui/feature-gate-used.stderr10
-rw-r--r--src/test/ui/feature-gate-wasm_import_memory.rs (renamed from src/test/compile-fail/feature-gate-wasm_import_memory.rs)0
-rw-r--r--src/test/ui/feature-gate-wasm_import_memory.stderr10
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-bench.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-bench.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr4
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr1354
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-deprecated.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr8
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr20
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-derive.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr38
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-inline.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr43
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_escape.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr12
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_use.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr20
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-proc_macro_derive.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr40
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-rustc_deprecated.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr46
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-stable.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-stable.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr46
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-test.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-test.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-test.stderr4
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs (renamed from src/test/compile-fail/feature-gate/issue-43106-gating-of-unstable.rs)0
-rw-r--r--src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr46
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.rs50
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.stderr13
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.rs53
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.stderr40
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.rs52
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr39
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.rs43
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr61
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.rs42
-rw-r--r--src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr42
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs63
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr46
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs64
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr36
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs53
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr75
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs51
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr36
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs54
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr36
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.rs52
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr36
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs59
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr37
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs53
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr46
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs57
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr46
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs24
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr14
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs24
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr14
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs (renamed from src/test/ui/nll/named-region-basic.rs)8
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr14
-rw-r--r--src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs (renamed from src/test/compile-fail/feature-gate-abi-sysv64.rs)16
-rw-r--r--src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs34
-rw-r--r--src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr38
-rw-r--r--src/test/ui/nll/named-region-basic.stderr31
-rw-r--r--src/test/ui/specialization-feature-gate-default.rs (renamed from src/test/compile-fail/specialization/specialization-feature-gate-default.rs)0
-rw-r--r--src/test/ui/specialization-feature-gate-default.stderr10
-rw-r--r--src/test/ui/specialization-feature-gate-overlap.rs (renamed from src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs)0
-rw-r--r--src/test/ui/specialization-feature-gate-overlap.stderr15
-rw-r--r--src/tools/compiletest/src/common.rs16
-rw-r--r--src/tools/compiletest/src/header.rs6
-rw-r--r--src/tools/compiletest/src/main.rs470
-rw-r--r--src/tools/compiletest/src/runtest.rs1454
-rw-r--r--src/tools/tidy/src/features.rs10
463 files changed, 10735 insertions, 2877 deletions
diff --git a/src/doc/not_found.md b/src/doc/not_found.md
index ebe7c59313f..f404aa046c1 100644
--- a/src/doc/not_found.md
+++ b/src/doc/not_found.md
@@ -13,20 +13,20 @@ Some things that might be helpful to you though:
 
 # Search
 
-* <form action="https://duckduckgo.com/">
+<form action="https://duckduckgo.com/">
     <input type="text" id="site-search" name="q" size="80"></input>
-    <input type="submit" value="Search DuckDuckGo">
-</form>
-* Rust doc search: <span id="core-search"></span>
+    <input type="submit" value="Search DuckDuckGo"></form>
+
+Rust doc search: <span id="core-search"></span>
 
 # Reference
 
-* [The Rust official site](https://www.rust-lang.org)
-* [The Rust reference](https://doc.rust-lang.org/reference/index.html)
+ * [The Rust official site](https://www.rust-lang.org)
+ * [The Rust reference](https://doc.rust-lang.org/reference/index.html)
 
 # Docs
 
-* [The standard library](https://doc.rust-lang.org/std/)
+[The standard library](https://doc.rust-lang.org/std/)
 
 <script>
 function get_url_fragments() {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index d4cd3f6264e..93cfc845b1f 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1084,9 +1084,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
         where F: FnOnce(&mut T) -> &mut U
     {
+        // FIXME(nll-rfc#40): fix borrow-check
+        let RefMut { value, borrow } = orig;
         RefMut {
-            value: f(orig.value),
-            borrow: orig.borrow,
+            value: f(value),
+            borrow: borrow,
         }
     }
 }
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index e173f43b5e6..06c29b47bf9 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -1776,12 +1776,18 @@ impl<I: Iterator> Iterator for Peekable<I> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<I::Item> {
-        match self.peeked.take() {
-            // the .take() below is just to avoid "move into pattern guard"
-            Some(ref mut v) if n == 0 => v.take(),
-            Some(None) => None,
-            Some(Some(_)) => self.iter.nth(n - 1),
-            None => self.iter.nth(n),
+        // FIXME(#6393): merge these when borrow-checking gets better.
+        if n == 0 {
+            match self.peeked.take() {
+                Some(v) => v,
+                None => self.iter.nth(n),
+            }
+        } else {
+            match self.peeked.take() {
+                Some(None) => None,
+                Some(Some(_)) => self.iter.nth(n - 1),
+                None => self.iter.nth(n),
+            }
         }
     }
 
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index fe2df226115..948ad104cdf 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -736,7 +736,7 @@ mod builtin {
     #[cfg(dox)]
     macro_rules! module_path { () => ({ /* compiler built-in */ }) }
 
-    /// Boolean evaluation of configuration flags.
+    /// Boolean evaluation of configuration flags, at compile-time.
     ///
     /// For more information, see the documentation for [`std::cfg!`].
     ///
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 12e6e843056..d8f3ec38cf3 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -338,6 +338,12 @@ impl<T> Option<T> {
 
     /// Returns the contained value or a default.
     ///
+    /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing
+    /// the result of a function call, it is recommended to use [`unwrap_or_else`],
+    /// which is lazily evaluated.
+    ///
+    /// [`unwrap_or_else`]: #method.unwrap_or_else
+    ///
     /// # Examples
     ///
     /// ```
@@ -451,11 +457,16 @@ impl<T> Option<T> {
     /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
     /// [`Ok(v)`] and [`None`] to [`Err(err)`].
     ///
+    /// Arguments passed to `ok_or` are eagerly evaluated; if you are passing the
+    /// result of a function call, it is recommended to use [`ok_or_else`], which is
+    /// lazily evaluated.
+    ///
     /// [`Result<T, E>`]: ../../std/result/enum.Result.html
     /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
     /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
     /// [`None`]: #variant.None
     /// [`Some(v)`]: #variant.Some
+    /// [`ok_or_else`]: #method.ok_or_else
     ///
     /// # Examples
     ///
@@ -644,6 +655,12 @@ impl<T> Option<T> {
 
     /// Returns the option if it contains a value, otherwise returns `optb`.
     ///
+    /// Arguments passed to `or` are eagerly evaluated; if you are passing the
+    /// result of a function call, it is recommended to use [`or_else`], which is
+    /// lazily evaluated.
+    ///
+    /// [`or_else`]: #method.or_else
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 959935242dc..2ace3d2aee8 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -625,8 +625,13 @@ impl<T, E> Result<T, E> {
 
     /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`.
     ///
+    /// Arguments passed to `or` are eagerly evaluated; if you are passing the
+    /// result of a function call, it is recommended to use [`or_else`], which is
+    /// lazily evaluated.
+    ///
     /// [`Ok`]: enum.Result.html#variant.Ok
     /// [`Err`]: enum.Result.html#variant.Err
+    /// [`or_else`]: #method.or_else
     ///
     /// # Examples
     ///
@@ -690,8 +695,13 @@ impl<T, E> Result<T, E> {
     /// Unwraps a result, yielding the content of an [`Ok`].
     /// Else, it returns `optb`.
     ///
+    /// Arguments passed to `unwrap_or` are eagerly evaluated; if you are passing
+    /// the result of a function call, it is recommended to use [`unwrap_or_else`],
+    /// which is lazily evaluated.
+    ///
     /// [`Ok`]: enum.Result.html#variant.Ok
     /// [`Err`]: enum.Result.html#variant.Err
+    /// [`unwrap_or_else`]: #method.unwrap_or_else
     ///
     /// # Examples
     ///
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 8089a88a9e8..85ae529ae32 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1641,14 +1641,14 @@ impl Foo {
 These attributes do not work on typedefs, since typedefs are just aliases.
 
 Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the
-discriminant size for C-like enums (when there is no associated data, e.g.
-`enum Color {Red, Blue, Green}`), effectively setting the size of the enum to
+discriminant size for enums with no data fields on any of the variants, e.g.
+`enum Color {Red, Blue, Green}`, effectively setting the size of the enum to
 the size of the provided type. Such an enum can be cast to a value of the same
 type as well. In short, `#[repr(u8)]` makes the enum behave like an integer
 with a constrained set of allowed values.
 
-Only C-like enums can be cast to numerical primitives, so this attribute will
-not apply to structs.
+Only field-less enums can be cast to numerical primitives, so this attribute
+will not apply to structs.
 
 `#[repr(packed)]` reduces padding to make the struct size smaller. The
 representation of enums isn't strictly defined in Rust, and this attribute
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index d95b825b9e5..0ef42177c14 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -14,7 +14,6 @@ use hir::map::DefPathHash;
 use hir::map::definitions::Definitions;
 use ich::{self, CachingCodemapView};
 use middle::cstore::CrateStore;
-use session::config::DebugInfoLevel::NoDebugInfo;
 use ty::{TyCtxt, fast_reject};
 use session::Session;
 
@@ -24,7 +23,7 @@ use std::cell::RefCell;
 use std::collections::HashMap;
 
 use syntax::ast;
-use syntax::attr;
+
 use syntax::codemap::CodeMap;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::symbol::Symbol;
@@ -51,7 +50,6 @@ pub struct StableHashingContext<'gcx> {
     body_resolver: BodyResolver<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
-    overflow_checks_enabled: bool,
     node_id_hashing_mode: NodeIdHashingMode,
 
     // Very often, we are hashing something that does not need the
@@ -89,8 +87,7 @@ impl<'gcx> StableHashingContext<'gcx> {
                definitions: &'gcx Definitions,
                cstore: &'gcx CrateStore)
                -> Self {
-        let hash_spans_initial = sess.opts.debuginfo != NoDebugInfo;
-        let check_overflow_initial = sess.overflow_checks();
+        let hash_spans_initial = !sess.opts.debugging_opts.incremental_ignore_spans;
 
         debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0);
         IGNORED_ATTR_NAMES.with(|names| {
@@ -110,7 +107,6 @@ impl<'gcx> StableHashingContext<'gcx> {
             raw_codemap: sess.codemap(),
             hash_spans: hash_spans_initial,
             hash_bodies: true,
-            overflow_checks_enabled: check_overflow_initial,
             node_id_hashing_mode: NodeIdHashingMode::HashDefPath,
         }
     }
@@ -120,11 +116,6 @@ impl<'gcx> StableHashingContext<'gcx> {
         self.sess
     }
 
-    pub fn force_span_hashing(mut self) -> Self {
-        self.hash_spans = true;
-        self
-    }
-
     #[inline]
     pub fn while_hashing_hir_bodies<F: FnOnce(&mut Self)>(&mut self,
                                                           hash_bodies: bool,
@@ -175,11 +166,6 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 
     #[inline]
-    pub fn hash_spans(&self) -> bool {
-        self.hash_spans
-    }
-
-    #[inline]
     pub fn hash_bodies(&self) -> bool {
         self.hash_bodies
     }
@@ -204,58 +190,13 @@ impl<'gcx> StableHashingContext<'gcx> {
         })
     }
 
-    pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self,
-                                                    item_attrs: &[ast::Attribute],
-                                                    is_const: bool,
-                                                    f: F) {
-        let prev_overflow_checks = self.overflow_checks_enabled;
-        if is_const || attr::contains_name(item_attrs, "rustc_inherit_overflow_checks") {
-            self.overflow_checks_enabled = true;
-        }
+    pub fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F) {
         let prev_hash_node_ids = self.node_id_hashing_mode;
         self.node_id_hashing_mode = NodeIdHashingMode::Ignore;
 
         f(self);
 
         self.node_id_hashing_mode = prev_hash_node_ids;
-        self.overflow_checks_enabled = prev_overflow_checks;
-    }
-
-    #[inline]
-    pub fn binop_can_panic_at_runtime(&self, binop: hir::BinOp_) -> bool
-    {
-        match binop {
-            hir::BiAdd |
-            hir::BiSub |
-            hir::BiShl |
-            hir::BiShr |
-            hir::BiMul => self.overflow_checks_enabled,
-
-            hir::BiDiv |
-            hir::BiRem => true,
-
-            hir::BiAnd |
-            hir::BiOr |
-            hir::BiBitXor |
-            hir::BiBitAnd |
-            hir::BiBitOr |
-            hir::BiEq |
-            hir::BiLt |
-            hir::BiLe |
-            hir::BiNe |
-            hir::BiGe |
-            hir::BiGt => false
-        }
-    }
-
-    #[inline]
-    pub fn unop_can_panic_at_runtime(&self, unop: hir::UnOp) -> bool
-    {
-        match unop {
-            hir::UnDeref |
-            hir::UnNot => false,
-            hir::UnNeg => self.overflow_checks_enabled,
-        }
     }
 }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 77bf3da679d..1533e37d7f7 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -529,63 +529,9 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Expr {
                 ref attrs
             } = *self;
 
-            let spans_always_on = match *node {
-                hir::ExprBox(..)        |
-                hir::ExprArray(..)      |
-                hir::ExprCall(..)       |
-                hir::ExprLit(..)        |
-                hir::ExprCast(..)       |
-                hir::ExprType(..)       |
-                hir::ExprIf(..)         |
-                hir::ExprWhile(..)      |
-                hir::ExprLoop(..)       |
-                hir::ExprMatch(..)      |
-                hir::ExprClosure(..)    |
-                hir::ExprBlock(..)      |
-                hir::ExprAssign(..)     |
-                hir::ExprTupField(..)   |
-                hir::ExprAddrOf(..)     |
-                hir::ExprBreak(..)      |
-                hir::ExprAgain(..)      |
-                hir::ExprRet(..)        |
-                hir::ExprYield(..)      |
-                hir::ExprInlineAsm(..)  |
-                hir::ExprRepeat(..)     |
-                hir::ExprTup(..)        |
-                hir::ExprMethodCall(..) |
-                hir::ExprPath(..)       |
-                hir::ExprStruct(..)     |
-                hir::ExprField(..)      => {
-                    // For these we only hash the span when debuginfo is on.
-                    false
-                }
-                // For the following, spans might be significant because of
-                // panic messages indicating the source location.
-                hir::ExprBinary(op, ..) => {
-                    hcx.binop_can_panic_at_runtime(op.node)
-                }
-                hir::ExprUnary(op, _) => {
-                    hcx.unop_can_panic_at_runtime(op)
-                }
-                hir::ExprAssignOp(op, ..) => {
-                    hcx.binop_can_panic_at_runtime(op.node)
-                }
-                hir::ExprIndex(..) => {
-                    true
-                }
-            };
-
-            if spans_always_on {
-                hcx.while_hashing_spans(true, |hcx| {
-                    span.hash_stable(hcx, hasher);
-                    node.hash_stable(hcx, hasher);
-                    attrs.hash_stable(hcx, hasher);
-                });
-            } else {
-                span.hash_stable(hcx, hasher);
-                node.hash_stable(hcx, hasher);
-                attrs.hash_stable(hcx, hasher);
-            }
+            span.hash_stable(hcx, hasher);
+            node.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
         })
     }
 }
@@ -712,15 +658,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem {
             span
         } = *self;
 
-        let is_const = match *node {
-            hir::TraitItemKind::Const(..) |
-            hir::TraitItemKind::Type(..) => true,
-            hir::TraitItemKind::Method(hir::MethodSig { constness, .. }, _) => {
-                constness == hir::Constness::Const
-            }
-        };
-
-        hcx.hash_hir_item_like(attrs, is_const, |hcx| {
+        hcx.hash_hir_item_like(|hcx| {
             name.hash_stable(hcx, hasher);
             attrs.hash_stable(hcx, hasher);
             generics.hash_stable(hcx, hasher);
@@ -757,15 +695,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem {
             span
         } = *self;
 
-        let is_const = match *node {
-            hir::ImplItemKind::Const(..) |
-            hir::ImplItemKind::Type(..) => true,
-            hir::ImplItemKind::Method(hir::MethodSig { constness, .. }, _) => {
-                constness == hir::Constness::Const
-            }
-        };
-
-        hcx.hash_hir_item_like(attrs, is_const, |hcx| {
+        hcx.hash_hir_item_like(|hcx| {
             name.hash_stable(hcx, hasher);
             vis.hash_stable(hcx, hasher);
             defaultness.hash_stable(hcx, hasher);
@@ -884,30 +814,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        let is_const = match self.node {
-            hir::ItemStatic(..)      |
-            hir::ItemConst(..)       => {
-                true
-            }
-            hir::ItemFn(_, _, constness, ..) => {
-                constness == hir::Constness::Const
-            }
-            hir::ItemUse(..)         |
-            hir::ItemExternCrate(..) |
-            hir::ItemForeignMod(..)  |
-            hir::ItemGlobalAsm(..)   |
-            hir::ItemMod(..)         |
-            hir::ItemAutoImpl(..) |
-            hir::ItemTrait(..)       |
-            hir::ItemImpl(..)        |
-            hir::ItemTy(..)          |
-            hir::ItemEnum(..)        |
-            hir::ItemStruct(..)      |
-            hir::ItemUnion(..)       => {
-                false
-            }
-        };
-
         let hir::Item {
             name,
             ref attrs,
@@ -918,7 +824,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
             span
         } = *self;
 
-        hcx.hash_hir_item_like(attrs, is_const, |hcx| {
+        hcx.hash_hir_item_like(|hcx| {
             name.hash_stable(hcx, hasher);
             attrs.hash_stable(hcx, hasher);
             node.hash_stable(hcx, hasher);
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 331b44ac119..32577ac46f3 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -55,48 +55,11 @@ for mir::UnsafetyViolationKind {
         }
     }
 }
-impl<'gcx> HashStable<StableHashingContext<'gcx>>
-for mir::Terminator<'gcx> {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'gcx>,
-                                          hasher: &mut StableHasher<W>) {
-        let mir::Terminator {
-            ref kind,
-            ref source_info,
-        } = *self;
-
-        let hash_spans_unconditionally = match *kind {
-            mir::TerminatorKind::Assert { .. } => {
-                // Assert terminators generate a panic message that contains the
-                // source location, so we always have to feed its span into the
-                // ICH.
-                true
-            }
-            mir::TerminatorKind::Goto { .. } |
-            mir::TerminatorKind::SwitchInt { .. } |
-            mir::TerminatorKind::Resume |
-            mir::TerminatorKind::Return |
-            mir::TerminatorKind::GeneratorDrop |
-            mir::TerminatorKind::Unreachable |
-            mir::TerminatorKind::Drop { .. } |
-            mir::TerminatorKind::DropAndReplace { .. } |
-            mir::TerminatorKind::Yield { .. } |
-            mir::TerminatorKind::Call { .. } |
-            mir::TerminatorKind::FalseEdges { .. } => false,
-        };
-
-        if hash_spans_unconditionally {
-            hcx.while_hashing_spans(true, |hcx| {
-                source_info.hash_stable(hcx, hasher);
-            })
-        } else {
-            source_info.hash_stable(hcx, hasher);
-        }
 
-        kind.hash_stable(hcx, hasher);
-    }
-}
+impl_stable_hash_for!(struct mir::Terminator<'tcx> {
+    kind,
+    source_info
+});
 
 impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearCrossCrate<T>
     where T: HashStable<StableHashingContext<'gcx>>
@@ -572,3 +535,15 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> {
 }
 
 impl_stable_hash_for!(struct mir::Location { block, statement_index });
+
+impl_stable_hash_for!(struct mir::ClosureRegionRequirements {
+    num_external_vids,
+    outlives_requirements
+});
+
+impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement {
+    free_region,
+    outlived_free_region,
+    blame_span
+});
+
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 9609ae5a0be..2655e2acbbd 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -84,6 +84,16 @@ for ty::RegionKind {
     }
 }
 
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::RegionVid {
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        use rustc_data_structures::indexed_vec::Idx;
+        self.index().hash_stable(hcx, hasher);
+    }
+}
+
 impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for ty::adjustment::AutoBorrow<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 96a980a1545..f5595d07340 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1062,6 +1062,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin)))
     }
 
+    /// Number of region variables created so far.
+    pub fn num_region_vars(&self) -> usize {
+        self.borrow_region_constraints().var_origins().len()
+    }
+
     /// Just a convenient wrapper of `next_region_var` for using during NLL.
     pub fn next_nll_region_var(&self, origin: NLLRegionVariableOrigin)
                                -> ty::Region<'tcx> {
@@ -1475,38 +1480,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         closure_kind_ty.to_opt_closure_kind()
     }
 
-    /// Obtain the signature of a function or closure.
-    /// For closures, unlike `tcx.fn_sig(def_id)`, this method will
-    /// work during the type-checking of the enclosing function and
-    /// return the closure signature in its partially inferred state.
-    pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
-        // Do we have an in-progress set of tables we are inferring?
-        if let Some(tables) = self.in_progress_tables {
-            // Is this a local item?
-            if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                // Is it a local *closure*?
-                if self.tcx.is_closure(def_id) {
-                    let hir_id = self.tcx.hir.node_to_hir_id(id);
-                    // Is this local closure contained within the tables we are inferring?
-                    if tables.borrow().local_id_root == Some(DefId::local(hir_id.owner)) {
-                        // if so, extract signature from there.
-                        let closure_ty = tables.borrow().node_id_to_type(hir_id);
-                        let (closure_def_id, closure_substs) = match closure_ty.sty {
-                            ty::TyClosure(closure_def_id, closure_substs) =>
-                                (closure_def_id, closure_substs),
-                            _ =>
-                                bug!("closure with non-closure type: {:?}", closure_ty),
-                        };
-                        assert_eq!(def_id, closure_def_id);
-                        let closure_sig_ty = closure_substs.closure_sig_ty(def_id, self.tcx);
-                        let closure_sig_ty = self.shallow_resolve(&closure_sig_ty);
-                        return closure_sig_ty.fn_sig(self.tcx);
-                    }
-                }
-            }
-        }
-
-        self.tcx.fn_sig(def_id)
+    /// Obtain the signature of a closure.  For closures, unlike
+    /// `tcx.fn_sig(def_id)`, this method will work during the
+    /// type-checking of the enclosing function and return the closure
+    /// signature in its partially inferred state.
+    pub fn closure_sig(
+        &self,
+        def_id: DefId,
+        substs: ty::ClosureSubsts<'tcx>
+    ) -> ty::PolyFnSig<'tcx> {
+        let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx);
+        let closure_sig_ty = self.shallow_resolve(&closure_sig_ty);
+        closure_sig_ty.fn_sig(self.tcx)
     }
 
     /// Normalizes associated types in `value`, potentially returning
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index c803e76aebe..64e601ab1e7 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1789,6 +1789,75 @@ pub struct GeneratorLayout<'tcx> {
     pub fields: Vec<LocalDecl<'tcx>>,
 }
 
+/// After we borrow check a closure, we are left with various
+/// requirements that we have inferred between the free regions that
+/// appear in the closure's signature or on its field types.  These
+/// requirements are then verified and proved by the closure's
+/// creating function. This struct encodes those requirements.
+///
+/// The requirements are listed as being between various
+/// `RegionVid`. The 0th region refers to `'static`; subsequent region
+/// vids refer to the free regions that appear in the closure (or
+/// generator's) type, in order of appearance. (This numbering is
+/// actually defined by the `UniversalRegions` struct in the NLL
+/// region checker. See for example
+/// `UniversalRegions::closure_mapping`.) Note that we treat the free
+/// regions in the closure's type "as if" they were erased, so their
+/// precise identity is not important, only their position.
+///
+/// Example: If type check produces a closure with the closure substs:
+///
+/// ```
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
+///     &'a String,                          // some upvar
+/// ]
+/// ```
+///
+/// here, there is one unique free region (`'a`) but it appears
+/// twice. We would "renumber" each occurence to a unique vid, as follows:
+///
+/// ```
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
+///     &'2 String,                          // some upvar
+/// ]
+/// ```
+///
+/// Now the code might impose a requirement like `'1: '2`. When an
+/// instance of the closure is created, the corresponding free regions
+/// can be extracted from its type and constrained to have the given
+/// outlives relationship.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct ClosureRegionRequirements {
+    /// The number of external regions defined on the closure.  In our
+    /// example above, it would be 3 -- one for `'static`, then `'1`
+    /// and `'2`. This is just used for a sanity check later on, to
+    /// make sure that the number of regions we see at the callsite
+    /// matches.
+    pub num_external_vids: usize,
+
+    /// Requirements between the various free regions defined in
+    /// indices.
+    pub outlives_requirements: Vec<ClosureOutlivesRequirement>,
+}
+
+/// Indicates an outlives constraint between two free-regions declared
+/// on the closure.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub struct ClosureOutlivesRequirement {
+    // This region ...
+    pub free_region: ty::RegionVid,
+
+    // .. must outlive this one.
+    pub outlived_free_region: ty::RegionVid,
+
+    // If not, report an error here.
+    pub blame_span: Span,
+}
+
 /*
  * TypeFoldable implementations for MIR types
  */
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 81e18fe536d..0dcd3e80810 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1084,6 +1084,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "dump hash information in textual format to stdout"),
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify incr. comp. hashes of green query instances"),
+    incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED],
+        "ignore spans during ICH computation -- used for testing"),
     dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
           "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 429771cca98..3342d13dd6e 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1339,26 +1339,27 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
     vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>)
     -> Progress<'tcx>
 {
-    let closure_typer = selcx.closure_typer();
-    let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
-        .subst(selcx.tcx(), vtable.substs.substs);
+    let tcx = selcx.tcx();
+    let infcx = selcx.infcx();
+    let closure_sig_ty = vtable.substs.closure_sig_ty(vtable.closure_def_id, tcx);
+    let closure_sig = infcx.shallow_resolve(&closure_sig_ty).fn_sig(tcx);
     let Normalized {
-        value: closure_type,
+        value: closure_sig,
         obligations
     } = normalize_with_depth(selcx,
                              obligation.param_env,
                              obligation.cause.clone(),
                              obligation.recursion_depth+1,
-                             &closure_type);
+                             &closure_sig);
 
-    debug!("confirm_closure_candidate: obligation={:?},closure_type={:?},obligations={:?}",
+    debug!("confirm_closure_candidate: obligation={:?},closure_sig={:?},obligations={:?}",
            obligation,
-           closure_type,
+           closure_sig,
            obligations);
 
     confirm_callable_candidate(selcx,
                                obligation,
-                               closure_type,
+                               closure_sig,
                                util::TupleArgumentsFlag::No)
         .with_addl_obligations(vtable.nested)
         .with_addl_obligations(obligations)
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 0c4071b8b5d..e70de0e566e 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -3183,8 +3183,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                       substs: ty::ClosureSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let closure_type = self.infcx.fn_sig(closure_def_id)
-            .subst(self.tcx(), substs.substs);
+        let closure_type = self.infcx.closure_sig(closure_def_id, substs);
         let ty::Binder((trait_ref, _)) =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
                                                          obligation.predicate.0.self_ty(), // (1)
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 70636f8b6fe..177c25ac5db 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
-use ty::subst::{Kind, Subst};
+use ty::subst::Kind;
 use traits;
 use syntax::abi::Abi;
 use util::ppaux;
@@ -311,7 +311,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let self_ty = tcx.mk_closure_from_closure_substs(
         closure_did, substs);
 
-    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
+    let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index 496284ad9c9..2d0a3799178 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -27,6 +27,7 @@ pub trait QueryConfig {
 pub(super) trait QueryDescription<'tcx>: QueryConfig {
     fn describe(tcx: TyCtxt, key: Self::Key) -> String;
 
+    #[inline]
     fn cache_on_disk(_: Self::Key) -> bool {
         false
     }
@@ -34,7 +35,7 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig {
     fn try_load_from_disk(_: TyCtxt<'_, 'tcx, 'tcx>,
                           _: SerializedDepNodeIndex)
                           -> Option<Self::Value> {
-        bug!("QueryDescription::load_from_disk() called for unsupport query.")
+        bug!("QueryDescription::load_from_disk() called for an unsupported query.")
     }
 }
 
@@ -166,6 +167,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
     fn describe(_tcx: TyCtxt, instance: ty::Instance<'tcx>) -> String {
         format!("computing the symbol for `{}`", instance)
     }
+
+    #[inline]
+    fn cache_on_disk(_: Self::Key) -> bool {
+        true
+    }
+
+    #[inline]
+    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              id: SerializedDepNodeIndex)
+                              -> Option<Self::Value> {
+        tcx.on_disk_query_result_cache.try_load_query_result(tcx, id)
+    }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> {
@@ -234,6 +247,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_sta
         format!("const checking if rvalue is promotable to static `{}`",
             tcx.item_path_str(def_id))
     }
+
+    #[inline]
+    fn cache_on_disk(_: Self::Key) -> bool {
+        true
+    }
+
+    #[inline]
+    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          id: SerializedDepNodeIndex)
+                          -> Option<Self::Value> {
+        tcx.on_disk_query_result_cache.try_load_query_result(tcx, id)
+    }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
@@ -254,6 +279,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::trans_fulfill_obligation<'tcx> {
     fn describe(tcx: TyCtxt, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
         format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
     }
+
+    #[inline]
+    fn cache_on_disk(_: Self::Key) -> bool {
+        true
+    }
+
+    #[inline]
+    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              id: SerializedDepNodeIndex)
+                              -> Option<Self::Value> {
+        tcx.on_disk_query_result_cache.try_load_query_result(tcx, id)
+    }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> {
@@ -567,3 +604,42 @@ impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> {
+    #[inline]
+    fn cache_on_disk(def_id: Self::Key) -> bool {
+        def_id.is_local()
+    }
+
+    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          id: SerializedDepNodeIndex)
+                          -> Option<Self::Value> {
+        let mir: Option<::mir::Mir<'tcx>> = tcx.on_disk_query_result_cache
+                                               .try_load_query_result(tcx, id);
+        mir.map(|x| tcx.alloc_mir(x))
+    }
+}
+
+macro_rules! impl_disk_cacheable_query(
+    ($query_name:ident, |$key:tt| $cond:expr) => {
+        impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {
+            #[inline]
+            fn cache_on_disk($key: Self::Key) -> bool {
+                $cond
+            }
+
+            #[inline]
+            fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      id: SerializedDepNodeIndex)
+                                      -> Option<Self::Value> {
+                tcx.on_disk_query_result_cache.try_load_query_result(tcx, 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!(mir_borrowck, |def_id| def_id.is_local());
+impl_disk_cacheable_query!(mir_const_qualif, |def_id| def_id.is_local());
+impl_disk_cacheable_query!(contains_extern_indicator, |_| true);
+impl_disk_cacheable_query!(def_symbol_name, |_| true);
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index fb3600182d8..848d2a0a7de 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -190,8 +190,10 @@ define_maps! { <'tcx>
     [] fn coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
 
     [] fn borrowck: BorrowCheck(DefId) -> Rc<BorrowCheckResult>,
-    // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead?
-    [] fn mir_borrowck: MirBorrowCheck(DefId) -> (),
+
+    /// Borrow checks the function body. If this is a closure, returns
+    /// additional requirements that the closure's creator must verify.
+    [] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements>,
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
index 8dc9b0877a0..079b518efd8 100644
--- a/src/librustc/ty/maps/on_disk_cache.rs
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -207,6 +207,16 @@ impl<'sess> OnDiskCache<'sess> {
 
             // Encode TypeckTables
             encode_query_results::<typeck_tables_of, _>(tcx, enc, qri)?;
+            encode_query_results::<optimized_mir, _>(tcx, enc, qri)?;
+            encode_query_results::<unsafety_check_result, _>(tcx, enc, qri)?;
+            encode_query_results::<borrowck, _>(tcx, enc, qri)?;
+            encode_query_results::<mir_borrowck, _>(tcx, enc, qri)?;
+            encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
+            encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
+            encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
+            encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
+            encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
+            encode_query_results::<trans_fulfill_obligation, _>(tcx, enc, qri)?;
         }
 
         // Encode diagnostics
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index fdaa13e7fd1..ec6d190b8bd 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -974,4 +974,7 @@ impl_load_from_cache!(
     BorrowCheck => borrowck,
     MirBorrowCheck => mir_borrowck,
     MirConstQualif => mir_const_qualif,
+    SymbolName => def_symbol_name,
+    ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
+    ContainsExternIndicator => contains_extern_indicator,
 );
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 05aab27dc2a..4f733b8f68a 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -356,6 +356,8 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// Returns the closure kind for this closure; only usable outside
     /// of an inference context, because in that context we know that
     /// there are no type variables.
+    ///
+    /// If you have an inference context, use `infcx.closure_kind()`.
     pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind {
         self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
     }
@@ -363,6 +365,8 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// Extracts the signature from the closure; only usable outside
     /// of an inference context, because in that context we know that
     /// there are no type variables.
+    ///
+    /// If you have an inference context, use `infcx.closure_sig()`.
     pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> {
         match self.closure_sig_ty(def_id, tcx).sty {
             ty::TyFnPtr(sig) => sig,
@@ -646,6 +650,17 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
 pub struct Binder<T>(pub T);
 
 impl<T> Binder<T> {
+    /// Wraps `value` in a binder, asserting that `value` does not
+    /// contain any bound regions that would be bound by the
+    /// binder. This is commonly used to 'inject' a value T into a
+    /// different binding level.
+    pub fn dummy<'tcx>(value: T) -> Binder<T>
+        where T: TypeFoldable<'tcx>
+    {
+        assert!(!value.has_escaping_regions());
+        Binder(value)
+    }
+
     /// Skips the binder and returns the "bound" value. This is a
     /// risky thing to do because it's easy to get confused about
     /// debruijn indices and the like. It is usually better to
@@ -700,6 +715,32 @@ impl<T> Binder<T> {
             Some(self.skip_binder().clone())
         }
     }
+
+    /// Given two things that have the same binder level,
+    /// and an operation that wraps on their contents, execute the operation
+    /// and then wrap its result.
+    ///
+    /// `f` should consider bound regions at depth 1 to be free, and
+    /// anything it produces with bound regions at depth 1 will be
+    /// bound in the resulting return value.
+    pub fn fuse<U,F,R>(self, u: Binder<U>, f: F) -> Binder<R>
+        where F: FnOnce(T, U) -> R
+    {
+        ty::Binder(f(self.0, u.0))
+    }
+
+    /// Split the contents into two things that share the same binder
+    /// level as the original, returning two distinct binders.
+    ///
+    /// `f` should consider bound regions at depth 1 to be free, and
+    /// anything it produces with bound regions at depth 1 will be
+    /// bound in the resulting return values.
+    pub fn split<U,V,F>(self, f: F) -> (Binder<U>, Binder<V>)
+        where F: FnOnce(T) -> (U, V)
+    {
+        let (u, v) = f(self.0);
+        (ty::Binder(u), ty::Binder(v))
+    }
 }
 
 /// Represents the projection of an associated type. In explicit UFCS
@@ -799,6 +840,9 @@ impl<'tcx> PolyFnSig<'tcx> {
     pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> {
         self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
     }
+    pub fn inputs_and_output(&self) -> ty::Binder<&'tcx Slice<Ty<'tcx>>> {
+        self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
+    }
     pub fn output(&self) -> ty::Binder<Ty<'tcx>> {
         self.map_bound_ref(|fn_sig| fn_sig.output().clone())
     }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index b1e9bc7e47c..b0f61e9a191 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -1069,7 +1069,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
 
         time(time_passes,
              "MIR borrow checking",
-             || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id) });
+             || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id); });
 
         time(time_passes,
              "MIR effect checking",
diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs
index ceb94f27dc3..2c33f805203 100644
--- a/src/librustc_errors/styled_buffer.rs
+++ b/src/librustc_errors/styled_buffer.rs
@@ -27,10 +27,21 @@ impl StyledBuffer {
     }
 
     fn replace_tabs(&mut self) {
-        for line in self.text.iter_mut() {
-            for c in line.iter_mut() {
+        for (line_pos, line) in self.text.iter_mut().enumerate() {
+            let mut tab_pos = vec![];
+            for (pos, c) in line.iter().enumerate() {
                 if *c == '\t' {
-                    *c = ' ';
+                    tab_pos.push(pos);
+                }
+            }
+            // start with the tabs at the end of the line to replace them with 4 space chars
+            for pos in tab_pos.iter().rev() {
+                assert_eq!(line.remove(*pos), '\t');
+                // fix the position of the style to match up after replacing the tabs
+                let s = self.styles[line_pos].remove(*pos);
+                for _ in 0..4 {
+                    line.insert(*pos, ' ');
+                    self.styles[line_pos].insert(*pos, s);
                 }
             }
         }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 722d0cad238..71b15643cbc 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -47,9 +47,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
             let mut hasher = StableHasher::new();
 
             hcx.while_hashing_hir_bodies(true, |hcx| {
-                hcx.while_hashing_spans(false, |hcx| {
-                    body.hash_stable(hcx, &mut hasher);
-                });
+                body.hash_stable(hcx, &mut hasher);
             });
 
             hasher.finish()
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index eb2bcfc93c5..3be99e97223 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -273,25 +273,23 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
         let lo = BytePos::decode(self)?;
         let hi = BytePos::decode(self)?;
 
+        if lo == BytePos(0) && hi == BytePos(0) {
+            // Don't try to rebase DUMMY_SP. Otherwise it will look like a valid
+            // Span again.
+            return Ok(DUMMY_SP)
+        }
+
+        if hi < lo {
+            // Consistently map invalid spans to DUMMY_SP.
+            return Ok(DUMMY_SP)
+        }
+
         let sess = if let Some(sess) = self.sess {
             sess
         } else {
             bug!("Cannot decode Span without Session.")
         };
 
-        let (lo, hi) = if lo > hi {
-            // Currently macro expansion sometimes produces invalid Span values
-            // where lo > hi. In order not to crash the compiler when trying to
-            // translate these values, let's transform them into something we
-            // can handle (and which will produce useful debug locations at
-            // least some of the time).
-            // This workaround is only necessary as long as macro expansion is
-            // not fixed. FIXME(#23480)
-            (lo, lo)
-        } else {
-            (lo, hi)
-        };
-
         let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap());
         let filemap = {
             // Optimize for the case that most spans within a translated item
@@ -321,6 +319,16 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
             }
         };
 
+        // Make sure our binary search above is correct.
+        debug_assert!(lo >= filemap.original_start_pos &&
+                      lo <= filemap.original_end_pos);
+
+        if hi < filemap.original_start_pos || hi > filemap.original_end_pos {
+            // `hi` points to a different FileMap than `lo` which is invalid.
+            // Again, map invalid Spans to DUMMY_SP.
+            return Ok(DUMMY_SP)
+        }
+
         let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
         let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 446aba3d3d7..97d8a677fe8 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -12,12 +12,14 @@
 
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::hir::map::definitions::DefPathData;
 use rustc::infer::InferCtxt;
 use rustc::ty::{self, ParamEnv, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Local, Location, Place};
 use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
 use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
+use rustc::mir::ClosureRegionRequirements;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_set::{self, IdxSetBuf};
@@ -36,6 +38,9 @@ use dataflow::move_paths::{IllegalMoveOriginKind, MoveError};
 use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MoveOutIndex, MovePathIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
+use std::fmt;
+use std::iter;
+
 use self::MutateMode::{JustWrite, WriteAndRead};
 
 pub(crate) mod nll;
@@ -47,7 +52,10 @@ pub fn provide(providers: &mut Providers) {
     };
 }
 
-fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+fn mir_borrowck<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> Option<ClosureRegionRequirements> {
     let input_mir = tcx.mir_validated(def_id);
     debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
 
@@ -55,21 +63,23 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.borrowck_mode.use_mir()
             && !tcx.sess.opts.debugging_opts.nll
     } {
-        return;
+        return None;
     }
 
-    tcx.infer_ctxt().enter(|infcx| {
+    let opt_closure_req = tcx.infer_ctxt().enter(|infcx| {
         let input_mir: &Mir = &input_mir.borrow();
-        do_mir_borrowck(&infcx, input_mir, def_id);
+        do_mir_borrowck(&infcx, input_mir, def_id)
     });
     debug!("mir_borrowck done");
+
+    opt_closure_req
 }
 
 fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     input_mir: &Mir<'gcx>,
     def_id: DefId,
-) {
+) -> Option<ClosureRegionRequirements> {
     let tcx = infcx.tcx;
     let attributes = tcx.get_attrs(def_id);
     let param_env = tcx.param_env(def_id);
@@ -87,7 +97,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         let mir = &mut mir;
 
         // Replace all regions with fresh inference variables.
-        Some(nll::replace_regions_in_mir(infcx, def_id, mir))
+        Some(nll::replace_regions_in_mir(infcx, def_id, param_env, mir))
     };
     let mir = &mir;
 
@@ -128,6 +138,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         move_data: move_data,
         param_env: param_env,
     };
+    let body_id = match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::StructCtor |
+        DefPathData::EnumVariant(_) => None,
+        _ => Some(tcx.hir.body_owned_by(id))
+    };
+
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let mut flow_inits = FlowInProgress::new(do_dataflow(
         tcx,
@@ -167,8 +183,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     ));
 
     // If we are in non-lexical mode, compute the non-lexical lifetimes.
-    let opt_regioncx = if let Some(free_regions) = free_regions {
-        Some(nll::compute_regions(
+    let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions {
+        let (regioncx, opt_closure_req) = nll::compute_regions(
             infcx,
             def_id,
             free_regions,
@@ -176,10 +192,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             param_env,
             &mut flow_inits,
             &mdpe.move_data,
-        ))
+        );
+        (Some(regioncx), opt_closure_req)
     } else {
         assert!(!tcx.sess.opts.debugging_opts.nll);
-        None
+        (None, None)
     };
     let flow_inits = flow_inits; // remove mut
 
@@ -189,6 +206,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         node_id: id,
         move_data: &mdpe.move_data,
         param_env: param_env,
+        locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) {
+            hir::BodyOwnerKind::Const |
+            hir::BodyOwnerKind::Static(_) => false,
+            hir::BodyOwnerKind::Fn => true,
+        },
         storage_dead_or_drop_error_reported: FxHashSet(),
     };
 
@@ -198,7 +220,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         id,
         &attributes,
         &dead_unwinds,
-        Borrows::new(tcx, mir, opt_regioncx),
+        Borrows::new(tcx, mir, opt_regioncx, def_id, body_id),
         |bd, i| bd.location(i),
     ));
 
@@ -211,6 +233,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     );
 
     mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
+
+    opt_closure_req
 }
 
 #[allow(dead_code)]
@@ -220,6 +244,13 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     node_id: ast::NodeId,
     move_data: &'cx MoveData<'tcx>,
     param_env: ParamEnv<'gcx>,
+    /// This keeps track of whether local variables are free-ed when the function
+    /// exits even without a `StorageDead`, which appears to be the case for
+    /// constants.
+    ///
+    /// I'm not sure this is the right approach - @eddyb could you try and
+    /// figure this out?
+    locals_are_invalidated_at_exit: bool,
     /// This field keeps track of when storage dead or drop errors are reported
     /// in order to stop duplicate error reporting and identify the conditions required
     /// for a "temporary value dropped here while still borrowed" error. See #45360.
@@ -306,8 +337,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
     }
 
     fn visit_block_entry(&mut self, bb: BasicBlock, flow_state: &Self::FlowState) {
-        let summary = flow_state.summary();
-        debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, summary);
+        debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, flow_state);
     }
 
     fn visit_statement_entry(
@@ -316,12 +346,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
         stmt: &Statement<'tcx>,
         flow_state: &Self::FlowState,
     ) {
-        let summary = flow_state.summary();
         debug!(
             "MirBorrowckCtxt::process_statement({:?}, {:?}): {}",
             location,
             stmt,
-            summary
+            flow_state
         );
         let span = stmt.source_info.span;
         match stmt.kind {
@@ -423,12 +452,11 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
         flow_state: &Self::FlowState,
     ) {
         let loc = location;
-        let summary = flow_state.summary();
         debug!(
             "MirBorrowckCtxt::process_terminator({:?}, {:?}): {}",
             location,
             term,
-            summary
+            flow_state
         );
         let span = term.source_info.span;
         match term.kind {
@@ -540,14 +568,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
 
                         if self.place_is_invalidated_at_exit(&borrow.place) {
                             debug!("borrow conflicts at exit {:?}", borrow);
-                            let borrow_span = self.mir.source_info(borrow.location).span;
                             // FIXME: should be talking about the region lifetime instead
                             // of just a span here.
                             let end_span = domain.opt_region_end_span(&borrow.region);
 
                             self.report_borrowed_value_does_not_live_long_enough(
                                 ContextKind::StorageDead.new(loc),
-                                (&borrow.place, borrow_span),
+                            (&borrow.place, end_span.unwrap_or(span)),
                                 end_span,
                             )
                         }
@@ -641,8 +668,9 @@ enum WriteKind {
 /// - Take flow state into consideration in `is_assignable()` for local variables
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum LocalMutationIsAllowed {
+    Move,
     Yes,
-    No,
+    No
 }
 
 #[derive(Copy, Clone)]
@@ -710,7 +738,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             context,
             (sd, place_span.0),
             flow_state,
-            |this, _index, borrow, common_prefix| match (rw, borrow.kind) {
+            |this, _index, borrow| match (rw, borrow.kind) {
                 (Read(_), BorrowKind::Shared) => Control::Continue,
                 (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut) => {
                     match kind {
@@ -727,7 +755,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             error_reported = true;
                             this.report_conflicting_borrow(
                                 context,
-                                common_prefix,
                                 place_span,
                                 bk,
                                 &borrow,
@@ -748,7 +775,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             error_reported = true;
                             this.report_conflicting_borrow(
                                 context,
-                                common_prefix,
                                 place_span,
                                 bk,
                                 &borrow,
@@ -934,7 +960,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     context,
                     (place, span),
                     (Deep, Write(WriteKind::Move)),
-                    LocalMutationIsAllowed::Yes,
+                    LocalMutationIsAllowed::Move,
                     flow_state,
                 );
 
@@ -952,14 +978,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
     /// Returns whether a borrow of this place is invalidated when the function
     /// exits
-    fn place_is_invalidated_at_exit(&self, place: &Place<'tcx>) -> bool {
+    fn place_is_invalidated_at_exit(&mut self, place: &Place<'tcx>) -> bool {
         debug!("place_is_invalidated_at_exit({:?})", place);
         let root_place = self.prefixes(place, PrefixSet::All).last().unwrap();
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
         // we'll have a memory leak) and assume that all statics have a destructor.
-        let (might_be_alive, will_be_dropped) = match root_place {
+        //
+        // FIXME: allow thread-locals to borrow other thread locals?
+        let (might_be_alive, will_be_dropped, local) = match root_place {
             Place::Static(statik) => {
                 // Thread-locals might be dropped after the function exits, but
                 // "true" statics will never be.
@@ -968,12 +996,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     .iter()
                     .any(|attr| attr.check_name("thread_local"));
 
-                (true, is_thread_local)
+                (true, is_thread_local, None)
             }
-            Place::Local(_) => {
+            Place::Local(local) => {
                 // Locals are always dropped at function exit, and if they
                 // have a destructor it would've been called already.
-                (false, true)
+                (false, self.locals_are_invalidated_at_exit, Some(*local))
             }
             Place::Projection(..) => {
                 bug!("root of {:?} is a projection ({:?})?", place, root_place)
@@ -996,8 +1024,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             PrefixSet::Shallow
         };
 
-        self.prefixes(place, prefix_set)
-            .any(|prefix| prefix == root_place)
+        let result =
+            self.prefixes(place, prefix_set).any(|prefix| prefix == root_place);
+
+        if result {
+            if let Some(local) = local {
+                if let Some(_) = self.storage_dead_or_drop_error_reported.replace(local) {
+                    debug!("place_is_invalidated_at_exit({:?}) - suppressed", place);
+                    return false;
+                }
+            }
+        }
+
+        result
     }
 }
 
@@ -1343,7 +1382,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 let local = &self.mir.local_decls[local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
-                        LocalMutationIsAllowed::Yes => Ok(()),
+                        LocalMutationIsAllowed::Yes |
+                        LocalMutationIsAllowed::Move => Ok(()),
                         LocalMutationIsAllowed::No => Err(place),
                     },
                     Mutability::Mut => Ok(()),
@@ -1368,10 +1408,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                     // Mutably borrowed data is mutable, but only if we have a
                                     // unique path to the `&mut`
                                     hir::MutMutable => {
-                                        if self.is_upvar_field_projection(&proj.base).is_some() {
-                                            self.is_mutable(&proj.base, is_local_mutation_allowed)
-                                        } else {
-                                            self.is_unique(&proj.base)
+                                        match self.is_upvar_field_projection(&proj.base) {
+                                            Some(field) if {
+                                                self.mir.upvar_decls[field.index()].by_ref
+                                            } => {
+                                                self.is_mutable(&proj.base,
+                                                                is_local_mutation_allowed)
+                                            }
+                                            _ => self.is_unique(&proj.base)
                                         }
                                     }
                                 }
@@ -1387,7 +1431,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
                             _ if base_ty.is_box() => {
-                                self.is_mutable(&proj.base, LocalMutationIsAllowed::No)
+                                self.is_mutable(&proj.base, is_local_mutation_allowed)
                             }
                             // Deref should only be for reference, pointers or boxes
                             _ => bug!("Deref of unexpected type: {:?}", base_ty),
@@ -1404,14 +1448,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                         if let Some(field) = field_projection {
                             let decl = &self.mir.upvar_decls[field.index()];
-
-                            return match decl.mutability {
-                                Mutability::Mut => self.is_unique(&proj.base),
-                                Mutability::Not => Err(place),
+                            debug!("decl.mutability={:?} local_mutation_is_allowed={:?} place={:?}",
+                                   decl, is_local_mutation_allowed, place);
+                            return match (decl.mutability, is_local_mutation_allowed) {
+                                (Mutability::Not, LocalMutationIsAllowed::No) |
+                                (Mutability::Not, LocalMutationIsAllowed::Yes) => Err(place),
+                                (Mutability::Not, LocalMutationIsAllowed::Move) |
+                                (Mutability::Mut, _) => self.is_unique(&proj.base),
                             };
                         }
 
-                        self.is_mutable(&proj.base, LocalMutationIsAllowed::No)
+                        self.is_mutable(&proj.base, is_local_mutation_allowed)
                     }
                 }
             }
@@ -1425,9 +1472,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // Local variables are unique
                 Ok(())
             }
-            Place::Static(..) => {
-                // Static variables are not
-                Err(place)
+            Place::Static(ref static_) => {
+                if !self.tcx.is_static_mut(static_.def_id) {
+                    Err(place)
+                } else {
+                    Ok(())
+                }
             }
             Place::Projection(ref proj) => {
                 match proj.elem {
@@ -1478,7 +1528,350 @@ enum NoMovePathFound {
     ReachedStatic,
 }
 
+/// The degree of overlap between 2 places for borrow-checking.
+enum Overlap {
+    /// The places might partially overlap - in this case, we give
+    /// up and say that they might conflict. This occurs when
+    /// different fields of a union are borrowed. For example,
+    /// if `u` is a union, we have no way of telling how disjoint
+    /// `u.a.x` and `a.b.y` are.
+    Arbitrary,
+    /// The places have the same type, and are either completely disjoint
+    /// or equal - i.e. they can't "partially" overlap as can occur with
+    /// unions. This is the "base case" on which we recur for extensions
+    /// of the place.
+    EqualOrDisjoint,
+    /// The places are disjoint, so we know all extensions of them
+    /// will also be disjoint.
+    Disjoint,
+}
+
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
+    // Given that the bases of `elem1` and `elem2` are always either equal
+    // or disjoint (and have the same type!), return the overlap situation
+    // between `elem1` and `elem2`.
+    fn place_element_conflict(&self,
+                               elem1: &Place<'tcx>,
+                               elem2: &Place<'tcx>)
+                               -> Overlap
+    {
+        match (elem1, elem2) {
+            (Place::Local(l1), Place::Local(l2)) => {
+                if l1 == l2 {
+                    // the same local - base case, equal
+                    debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL");
+                    Overlap::EqualOrDisjoint
+                } else {
+                    // different locals - base case, disjoint
+                    debug!("place_element_conflict: DISJOINT-LOCAL");
+                    Overlap::Disjoint
+                }
+            }
+            (Place::Static(..), Place::Static(..)) => {
+                // Borrows of statics do not have to be tracked here.
+                debug!("place_element_conflict: IGNORED-STATIC");
+                Overlap::Disjoint
+            }
+            (Place::Local(_), Place::Static(_)) |
+            (Place::Static(_), Place::Local(_)) => {
+                debug!("place_element_conflict: DISJOINT-STATIC-LOCAL");
+                Overlap::Disjoint
+            }
+            (Place::Projection(pi1), Place::Projection(pi2)) => {
+                match (&pi1.elem, &pi2.elem) {
+                    (ProjectionElem::Deref, ProjectionElem::Deref) => {
+                        // derefs (e.g. `*x` vs. `*x`) - recur.
+                        debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
+                        Overlap::EqualOrDisjoint
+                    }
+                    (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
+                        if f1 == f2 {
+                            // same field (e.g. `a.y` vs. `a.y`) - recur.
+                            debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
+                            Overlap::EqualOrDisjoint
+                        } else {
+                            let ty = pi1.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                            match ty.sty {
+                                ty::TyAdt(def, _) if def.is_union() => {
+                                    // Different fields of a union, we are basically stuck.
+                                    debug!("place_element_conflict: STUCK-UNION");
+                                    Overlap::Arbitrary
+                                }
+                                _ => {
+                                    // Different fields of a struct (`a.x` vs. `a.y`). Disjoint!
+                                    debug!("place_element_conflict: DISJOINT-FIELD");
+                                    Overlap::Disjoint
+                                }
+                            }
+                        }
+                    }
+                    (ProjectionElem::Downcast(_, v1), ProjectionElem::Downcast(_, v2)) => {
+                        // different variants are treated as having disjoint fields,
+                        // even if they occupy the same "space", because it's
+                        // impossible for 2 variants of the same enum to exist
+                        // (and therefore, to be borrowed) at the same time.
+                        //
+                        // Note that this is different from unions - we *do* allow
+                        // this code to compile:
+                        //
+                        // ```
+                        // fn foo(x: &mut Result<i32, i32>) {
+                        //     let mut v = None;
+                        //     if let Ok(ref mut a) = *x {
+                        //         v = Some(a);
+                        //     }
+                        //     // here, you would *think* that the
+                        //     // *entirety* of `x` would be borrowed,
+                        //     // but in fact only the `Ok` variant is,
+                        //     // so the `Err` variant is *entirely free*:
+                        //     if let Err(ref mut a) = *x {
+                        //         v = Some(a);
+                        //     }
+                        //     drop(v);
+                        // }
+                        // ```
+                        if v1 == v2 {
+                            debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
+                            Overlap::EqualOrDisjoint
+                        } else {
+                            debug!("place_element_conflict: DISJOINT-FIELD");
+                            Overlap::Disjoint
+                        }
+                    }
+                    (ProjectionElem::Index(..), ProjectionElem::Index(..)) |
+                    (ProjectionElem::Index(..), ProjectionElem::ConstantIndex { .. }) |
+                    (ProjectionElem::Index(..), ProjectionElem::Subslice { .. }) |
+                    (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Index(..)) |
+                    (ProjectionElem::ConstantIndex { .. }, ProjectionElem::ConstantIndex { .. }) |
+                    (ProjectionElem::ConstantIndex { .. }, ProjectionElem::Subslice { .. }) |
+                    (ProjectionElem::Subslice { .. }, ProjectionElem::Index(..)) |
+                    (ProjectionElem::Subslice { .. }, ProjectionElem::ConstantIndex { .. }) |
+                    (ProjectionElem::Subslice { .. }, ProjectionElem::Subslice { .. }) => {
+                        // Array indexes (`a[0]` vs. `a[i]`). These can either be disjoint
+                        // (if the indexes differ) or equal (if they are the same), so this
+                        // is the recursive case that gives "equal *or* disjoint" its meaning.
+                        //
+                        // Note that by construction, MIR at borrowck can't subdivide
+                        // `Subslice` accesses (e.g. `a[2..3][i]` will never be present) - they
+                        // are only present in slice patterns, and we "merge together" nested
+                        // slice patterns. That means we don't have to think about these. It's
+                        // probably a good idea to assert this somewhere, but I'm too lazy.
+                        //
+                        // FIXME(#8636) we might want to return Disjoint if
+                        // both projections are constant and disjoint.
+                        debug!("place_element_conflict: DISJOINT-OR-EQ-ARRAY");
+                        Overlap::EqualOrDisjoint
+                    }
+
+                    (ProjectionElem::Deref, _) |
+                    (ProjectionElem::Field(..), _) |
+                    (ProjectionElem::Index(..), _) |
+                    (ProjectionElem::ConstantIndex { .. }, _) |
+                    (ProjectionElem::Subslice { .. }, _) |
+                    (ProjectionElem::Downcast(..), _) => {
+                        bug!("mismatched projections in place_element_conflict: {:?} and {:?}",
+
+                             elem1, elem2)
+                    }
+                }
+            }
+            (Place::Projection(_), _) |
+            (_, Place::Projection(_)) => {
+                bug!("unexpected elements in place_element_conflict: {:?} and {:?}",
+                     elem1, elem2)
+            }
+        }
+    }
+    fn borrow_conflicts_with_place(&mut self,
+                                    borrow: &BorrowData<'tcx>,
+                                    place: &Place<'tcx>,
+                                    access: ShallowOrDeep)
+                                    -> bool
+    {
+        debug!("borrow_conflicts_with_place({:?},{:?},{:?})", borrow, place, access);
+
+        // Return all the prefixes of `place` in reverse order, including
+        // downcasts.
+        fn place_elements<'a, 'tcx>(place: &'a Place<'tcx>) -> Vec<&'a Place<'tcx>>
+        {
+            let mut result = vec![];
+            let mut place = place;
+            loop {
+                result.push(place);
+                match place {
+                    Place::Projection(interior) => {
+                        place = &interior.base;
+                    }
+                    Place::Local(_) | Place::Static(_) => {
+                        result.reverse();
+                        return result;
+                    }
+                }
+            }
+        }
+
+        let borrow_components = place_elements(&borrow.place);
+        let access_components = place_elements(place);
+        debug!("borrow_conflicts_with_place: components {:?} / {:?}",
+               borrow_components, access_components);
+
+        let borrow_components = borrow_components.into_iter()
+             .map(Some).chain(iter::repeat(None));
+        let access_components = access_components.into_iter()
+             .map(Some).chain(iter::repeat(None));
+        // The borrowck rules for proving disjointness are applied from the "root" of the
+        // borrow forwards, iterating over "similar" projections in lockstep until
+        // we can prove overlap one way or another. Essentially, we treat `Overlap` as
+        // a monoid and report a conflict if the product ends up not being `Disjoint`.
+        //
+        // At each step, if we didn't run out of borrow or place, we know that our elements
+        // have the same type, and that they only overlap if they are the identical.
+        //
+        // For example, if we are comparing these:
+        // BORROW:  (*x1[2].y).z.a
+        // ACCESS:  (*x1[i].y).w.b
+        //
+        // Then our steps are:
+        //       x1         |   x1          -- places are the same
+        //       x1[2]      |   x1[i]       -- equal or disjoint (disjoint if indexes differ)
+        //       x1[2].y    |   x1[i].y     -- equal or disjoint
+        //      *x1[2].y    |  *x1[i].y     -- equal or disjoint
+        //     (*x1[2].y).z | (*x1[i].y).w  -- we are disjoint and don't need to check more!
+        //
+        // Because `zip` does potentially bad things to the iterator inside, this loop
+        // also handles the case where the access might be a *prefix* of the borrow, e.g.
+        //
+        // BORROW:  (*x1[2].y).z.a
+        // ACCESS:  x1[i].y
+        //
+        // Then our steps are:
+        //       x1         |   x1          -- places are the same
+        //       x1[2]      |   x1[i]       -- equal or disjoint (disjoint if indexes differ)
+        //       x1[2].y    |   x1[i].y     -- equal or disjoint
+        //
+        // -- here we run out of access - the borrow can access a part of it. If this
+        // is a full deep access, then we *know* the borrow conflicts with it. However,
+        // if the access is shallow, then we can proceed:
+        //
+        //       x1[2].y    | (*x1[i].y)    -- a deref! the access can't get past this, so we
+        //                                     are disjoint
+        //
+        // Our invariant is, that at each step of the iteration:
+        //  - If we didn't run out of access to match, our borrow and access are comparable
+        //    and either equal or disjoint.
+        //  - If we did run out of accesss, the borrow can access a part of it.
+        for (borrow_c, access_c) in borrow_components.zip(access_components) {
+            // loop invariant: borrow_c is always either equal to access_c or disjoint from it.
+            debug!("borrow_conflicts_with_place: {:?} vs. {:?}", borrow_c, access_c);
+            match (borrow_c, access_c) {
+                (None, _) => {
+                    // If we didn't run out of access, the borrow can access all of our
+                    // place (e.g. a borrow of `a.b` with an access to `a.b.c`),
+                    // so we have a conflict.
+                    //
+                    // If we did, then we still know that the borrow can access a *part*
+                    // of our place that our access cares about (a borrow of `a.b.c`
+                    // with an access to `a.b`), so we still have a conflict.
+                    //
+                    // FIXME: Differs from AST-borrowck; includes drive-by fix
+                    // to #38899. Will probably need back-compat mode flag.
+                    debug!("borrow_conflict_with_place: full borrow, CONFLICT");
+                    return true;
+                }
+                (Some(borrow_c), None) => {
+                    // We know that the borrow can access a part of our place. This
+                    // is a conflict if that is a part our access cares about.
+
+                    let (base, elem) = match borrow_c {
+                        Place::Projection(box Projection { base, elem }) => (base, elem),
+                        _ => bug!("place has no base?")
+                    };
+                    let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
+
+                    match (elem, &base_ty.sty, access) {
+                        (_, _, Shallow(Some(ArtificialField::Discriminant))) |
+                        (_, _, Shallow(Some(ArtificialField::ArrayLength))) => {
+                            // The discriminant and array length are like
+                            // additional fields on the type; they do not
+                            // overlap any existing data there. Furthermore,
+                            // they cannot actually be a prefix of any
+                            // borrowed place (at least in MIR as it is
+                            // currently.)
+                            //
+                            // e.g. a (mutable) borrow of `a[5]` while we read the
+                            // array length of `a`.
+                            debug!("borrow_conflicts_with_place: implicit field");
+                            return false;
+                        }
+
+                        (ProjectionElem::Deref, _, Shallow(None)) => {
+                            // e.g. a borrow of `*x.y` while we shallowly access `x.y` or some
+                            // prefix thereof - the shallow access can't touch anything behind
+                            // the pointer.
+                            debug!("borrow_conflicts_with_place: shallow access behind ptr");
+                            return false;
+                        }
+                        (ProjectionElem::Deref, ty::TyRef(_, ty::TypeAndMut {
+                            ty: _, mutbl: hir::MutImmutable
+                        }), _) => {
+                            // the borrow goes through a dereference of a shared reference.
+                            //
+                            // I'm not sure why we are tracking these borrows - shared
+                            // references can *always* be aliased, which means the
+                            // permission check already account for this borrow.
+                            debug!("borrow_conflicts_with_place: behind a shared ref");
+                            return false;
+                        }
+
+                        (ProjectionElem::Deref, _, Deep) |
+                        (ProjectionElem::Field { .. }, _, _) |
+                        (ProjectionElem::Index { ..}, _, _) |
+                        (ProjectionElem::ConstantIndex { .. }, _, _) |
+                        (ProjectionElem::Subslice { .. }, _, _) |
+                        (ProjectionElem::Downcast { .. }, _, _) => {
+                            // Recursive case. This can still be disjoint on a
+                            // further iteration if this a shallow access and
+                            // there's a deref later on, e.g. a borrow
+                            // of `*x.y` while accessing `x`.
+                        }
+                    }
+                }
+                (Some(borrow_c), Some(access_c)) => {
+                    match self.place_element_conflict(&borrow_c, access_c) {
+                        Overlap::Arbitrary => {
+                            // We have encountered different fields of potentially
+                            // the same union - the borrow now partially overlaps.
+                            //
+                            // There is no *easy* way of comparing the fields
+                            // further on, because they might have different types
+                            // (e.g. borrows of `u.a.0` and `u.b.y` where `.0` and
+                            // `.y` come from different structs).
+                            //
+                            // We could try to do some things here - e.g. count
+                            // dereferences - but that's probably not a good
+                            // idea, at least for now, so just give up and
+                            // report a conflict. This is unsafe code anyway so
+                            // the user could always use raw pointers.
+                            debug!("borrow_conflicts_with_place: arbitrary -> conflict");
+                            return true;
+                        }
+                        Overlap::EqualOrDisjoint => {
+                            // This is the recursive case - proceed to the next element.
+                        }
+                        Overlap::Disjoint => {
+                            // We have proven the borrow disjoint - further
+                            // projections will remain disjoint.
+                            debug!("borrow_conflicts_with_place: disjoint");
+                            return false;
+                        }
+                    }
+
+                }
+            }
+        }
+        unreachable!("iter::repeat returned None")
+    }
+
     fn each_borrow_involving_path<F>(
         &mut self,
         _context: Context,
@@ -1486,7 +1879,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         flow_state: &InProgress<'cx, 'gcx, 'tcx>,
         mut op: F,
     ) where
-        F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Place<'tcx>) -> Control,
+        F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>) -> Control,
     {
         let (access, place) = access_place;
 
@@ -1501,47 +1894,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         'next_borrow: for i in flow_state.borrows.elems_incoming() {
             let borrowed = &data[i];
 
-            // Is `place` (or a prefix of it) already borrowed? If
-            // so, that's relevant.
-            //
-            // FIXME: Differs from AST-borrowck; includes drive-by fix
-            // to #38899. Will probably need back-compat mode flag.
-            for accessed_prefix in self.prefixes(place, PrefixSet::All) {
-                if *accessed_prefix == borrowed.place {
-                    // FIXME: pass in enum describing case we are in?
-                    let ctrl = op(self, i, borrowed, accessed_prefix);
-                    if ctrl == Control::Break {
-                        return;
-                    }
-                }
-            }
-
-            // Is `place` a prefix (modulo access type) of the
-            // `borrowed.place`? If so, that's relevant.
-
-            let prefix_kind = match access {
-                Shallow(Some(ArtificialField::Discriminant)) |
-                Shallow(Some(ArtificialField::ArrayLength)) => {
-                    // The discriminant and array length are like
-                    // additional fields on the type; they do not
-                    // overlap any existing data there. Furthermore,
-                    // they cannot actually be a prefix of any
-                    // borrowed place (at least in MIR as it is
-                    // currently.)
-                    continue 'next_borrow;
-                }
-                Shallow(None) => PrefixSet::Shallow,
-                Deep => PrefixSet::Supporting,
-            };
-
-            for borrowed_prefix in self.prefixes(&borrowed.place, prefix_kind) {
-                if borrowed_prefix == place {
-                    // FIXME: pass in enum describing case we are in?
-                    let ctrl = op(self, i, borrowed, borrowed_prefix);
-                    if ctrl == Control::Break {
-                        return;
-                    }
-                }
+            if self.borrow_conflicts_with_place(borrowed, place, access) {
+                let ctrl = op(self, i, borrowed);
+                if ctrl == Control::Break { return; }
             }
         }
     }
@@ -1595,6 +1950,7 @@ mod prefixes {
     }
 
     #[derive(Copy, Clone, PartialEq, Eq, Debug)]
+    #[allow(dead_code)]
     pub(super) enum PrefixSet {
         /// Doesn't stop until it returns the base case (a Local or
         /// Static prefix).
@@ -1907,17 +2263,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     fn report_conflicting_borrow(
         &mut self,
         context: Context,
-        common_prefix: &Place<'tcx>,
         (place, span): (&Place<'tcx>, Span),
         gen_borrow_kind: BorrowKind,
         issued_borrow: &BorrowData,
         end_issued_loan_span: Option<Span>,
     ) {
-        use self::prefixes::IsPrefixOf;
-
-        assert!(common_prefix.is_prefix_of(place));
-        assert!(common_prefix.is_prefix_of(&issued_borrow.place));
-
         let issued_span = self.retrieve_borrow_span(issued_borrow);
 
         let new_closure_span = self.find_closure_span(span, context.loc);
@@ -2373,8 +2723,10 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
         xform_move_outs(&mut self.move_outs);
         xform_ever_inits(&mut self.ever_inits);
     }
+}
 
-    fn summary(&self) -> String {
+impl<'b, 'gcx, 'tcx> fmt::Display for InProgress<'b, 'gcx, 'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let mut s = String::new();
 
         s.push_str("borrows in effect: [");
@@ -2451,7 +2803,7 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
         });
         s.push_str("]");
 
-        return s;
+        fmt::Display::fmt(&s, fmt)
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 804f5e26875..4ff299efb95 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use rustc::hir::def_id::DefId;
-use rustc::mir::Mir;
+use rustc::mir::{ClosureRegionRequirements, Mir};
 use rustc::infer::InferCtxt;
 use rustc::ty::{self, RegionKind, RegionVid};
 use rustc::util::nodemap::FxHashMap;
 use std::collections::BTreeSet;
+use std::io;
 use transform::MirSource;
 use transform::type_check;
 use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
@@ -22,6 +23,7 @@ use dataflow::MaybeInitializedLvals;
 use dataflow::move_paths::MoveData;
 
 use util as mir_util;
+use util::pretty::{self, ALIGN};
 use self::mir_util::PassWhere;
 
 mod constraint_generation;
@@ -35,20 +37,26 @@ use self::region_infer::RegionInferenceContext;
 mod renumber;
 
 /// Rewrites the regions in the MIR to use NLL variables, also
-/// scraping out the set of free regions (e.g., region parameters)
+/// scraping out the set of universal regions (e.g., region parameters)
 /// declared on the function. That set will need to be given to
 /// `compute_regions`.
 pub(in borrow_check) fn replace_regions_in_mir<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
     def_id: DefId,
+    param_env: ty::ParamEnv<'tcx>,
     mir: &mut Mir<'tcx>,
 ) -> UniversalRegions<'tcx> {
-    // Compute named region information.
-    let universal_regions = universal_regions::universal_regions(infcx, def_id);
+    debug!("replace_regions_in_mir(def_id={:?})", def_id);
 
-    // Replace all regions with fresh inference variables.
+    // Compute named region information. This also renumbers the inputs/outputs.
+    let universal_regions = UniversalRegions::new(infcx, def_id, param_env);
+
+    // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, &universal_regions, mir);
 
+    let source = MirSource::item(def_id);
+    mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, mir, |_, _| Ok(()));
+
     universal_regions
 }
 
@@ -63,7 +71,10 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowInProgress<MaybeInitializedLvals<'cx, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
-) -> RegionInferenceContext<'tcx> {
+) -> (
+    RegionInferenceContext<'tcx>,
+    Option<ClosureRegionRequirements>,
+) {
     // Run the MIR type-checker.
     let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap();
     let constraint_sets = &type_check::type_check(infcx, mir_node_id, param_env, mir);
@@ -71,13 +82,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // Create the region inference context, taking ownership of the region inference
     // data that was contained in `infcx`.
     let var_origins = infcx.take_region_var_origins();
-    let mut regioncx = RegionInferenceContext::new(var_origins, &universal_regions, mir);
-    subtype_constraint_generation::generate(
-        &mut regioncx,
-        &universal_regions,
-        mir,
-        constraint_sets,
-    );
+    let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir);
+    subtype_constraint_generation::generate(&mut regioncx, mir, constraint_sets);
 
     // Compute what is live where.
     let liveness = &LivenessResults {
@@ -110,13 +116,24 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     );
 
     // Solve the region constraints.
-    regioncx.solve(infcx, &mir);
+    let closure_region_requirements = regioncx.solve(infcx, &mir, def_id);
 
     // Dump MIR results into a file, if that is enabled. This let us
-    // write unit-tests.
-    dump_mir_results(infcx, liveness, MirSource::item(def_id), &mir, &regioncx);
+    // write unit-tests, as well as helping with debugging.
+    dump_mir_results(
+        infcx,
+        liveness,
+        MirSource::item(def_id),
+        &mir,
+        &regioncx,
+        &closure_region_requirements,
+    );
 
-    regioncx
+    // We also have a `#[rustc_nll]` annotation that causes us to dump
+    // information
+    dump_annotation(infcx, &mir, def_id, &regioncx, &closure_region_requirements);
+
+    (regioncx, closure_region_requirements)
 }
 
 struct LivenessResults {
@@ -130,6 +147,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     source: MirSource,
     mir: &Mir<'tcx>,
     regioncx: &RegionInferenceContext,
+    closure_region_requirements: &Option<ClosureRegionRequirements>,
 ) {
     if !mir_util::dump_enabled(infcx.tcx, "nll", source) {
         return;
@@ -164,9 +182,17 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
     mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, mir, |pass_where, out| {
         match pass_where {
             // Before the CFG, dump out the values for each region variable.
-            PassWhere::BeforeCFG => for region in regioncx.regions() {
-                writeln!(out, "| {:?}: {}", region, regioncx.region_value_str(region))?;
-            },
+            PassWhere::BeforeCFG => {
+                regioncx.dump_mir(out)?;
+
+                if let Some(closure_region_requirements) = closure_region_requirements {
+                    writeln!(out, "|")?;
+                    writeln!(out, "| Free Region Constraints")?;
+                    for_each_region_constraint(closure_region_requirements, &mut |msg| {
+                        writeln!(out, "| {}", msg)
+                    })?;
+                }
+            }
 
             // Before each basic block, dump out the values
             // that are live on entry to the basic block.
@@ -180,19 +206,96 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
                     &regular_liveness_per_location[&location],
                     &drop_liveness_per_location[&location],
                 );
-                writeln!(out, "            | Live variables at {:?}: {}", location, s)?;
+                writeln!(
+                    out,
+                    "{:ALIGN$} | Live variables on entry to {:?}: {}",
+                    "",
+                    location,
+                    s,
+                    ALIGN = ALIGN
+                )?;
             }
 
             PassWhere::AfterLocation(_) | PassWhere::AfterCFG => {}
         }
         Ok(())
     });
+
+    // Also dump the inference graph constraints as a graphviz file.
+    let _: io::Result<()> = do catch {
+        let mut file =
+            pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
+        regioncx.dump_graphviz(&mut file)
+    };
+}
+
+fn dump_annotation<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    mir: &Mir<'tcx>,
+    mir_def_id: DefId,
+    regioncx: &RegionInferenceContext,
+    closure_region_requirements: &Option<ClosureRegionRequirements>,
+) {
+    let tcx = infcx.tcx;
+    let base_def_id = tcx.closure_base_def_id(mir_def_id);
+    if !tcx.has_attr(base_def_id, "rustc_regions") {
+        return;
+    }
+
+    // When the enclosing function is tagged with `#[rustc_regions]`,
+    // we dump out various bits of state as warnings. This is useful
+    // for verifying that the compiler is behaving as expected.  These
+    // warnings focus on the closure region requirements -- for
+    // viewing the intraprocedural state, the -Zdump-mir output is
+    // better.
+
+    if let Some(closure_region_requirements) = closure_region_requirements {
+        let mut err = tcx.sess
+            .diagnostic()
+            .span_note_diag(mir.span, "External requirements");
+
+        regioncx.annotate(&mut err);
+
+        err.note(&format!(
+            "number of external vids: {}",
+            closure_region_requirements.num_external_vids
+        ));
+
+        // Dump the region constraints we are imposing *between* those
+        // newly created variables.
+        for_each_region_constraint(closure_region_requirements, &mut |msg| {
+            err.note(msg);
+            Ok(())
+        }).unwrap();
+
+        err.emit();
+    } else {
+        let mut err = tcx.sess
+            .diagnostic()
+            .span_note_diag(mir.span, "No external requirements");
+        regioncx.annotate(&mut err);
+        err.emit();
+    }
+}
+
+fn for_each_region_constraint(
+    closure_region_requirements: &ClosureRegionRequirements,
+    with_msg: &mut FnMut(&str) -> io::Result<()>,
+) -> io::Result<()> {
+    for req in &closure_region_requirements.outlives_requirements {
+        with_msg(&format!(
+            "where {:?}: {:?}",
+            req.free_region,
+            req.outlived_free_region,
+        ))?;
+    }
+    Ok(())
 }
 
 /// Right now, we piggy back on the `ReVar` to store our NLL inference
 /// regions. These are indexed with `RegionVid`. This method will
 /// assert that the region is a `ReVar` and extract its interal index.
-/// This is reasonable because in our MIR we replace all free regions
+/// This is reasonable because in our MIR we replace all universal regions
 /// with inference variables.
 pub trait ToRegionVid {
     fn to_region_vid(&self) -> RegionVid;
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
new file mode 100644
index 00000000000..906efaef887
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/region_infer/annotation.rs
@@ -0,0 +1,48 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! As part of the NLL unit tests, you can annotate a function with
+//! `#[rustc_regions]`, and we will emit information about the region
+//! inference context and -- in particular -- the external constraints
+//! that this region imposes on others. The methods in this file
+//! handle the part about dumping the inference context internal
+//! state.
+
+use rustc::ty;
+use rustc_errors::DiagnosticBuilder;
+use super::RegionInferenceContext;
+
+impl<'gcx, 'tcx> RegionInferenceContext<'tcx> {
+    /// Write out our state into the `.mir` files.
+    pub(crate) fn annotate(&self, err: &mut DiagnosticBuilder<'_>) {
+        match self.universal_regions.defining_ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                err.note(&format!(
+                    "defining type: {:?} with closure substs {:#?}",
+                    def_id,
+                    &substs.substs[..]
+                ));
+            }
+            ty::TyFnDef(def_id, substs) => {
+                err.note(&format!(
+                    "defining type: {:?} with substs {:#?}",
+                    def_id,
+                    &substs[..]
+                ));
+            }
+            _ => {
+                err.note(&format!(
+                    "defining type: {:?}",
+                    self.universal_regions.defining_ty
+                ));
+            }
+        }
+    }
+}
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
new file mode 100644
index 00000000000..5477308bde9
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
@@ -0,0 +1,100 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! As part of generating the regions, if you enable `-Zdump-mir=nll`,
+//! we will generate an annotated copy of the MIR that includes the
+//! state of region inference. This code handles emitting the region
+//! context internal state.
+
+use std::io::{self, Write};
+use super::{Constraint, RegionInferenceContext};
+
+// Room for "'_#NNNNr" before things get misaligned.
+// Easy enough to fix if this ever doesn't seem like
+// enough.
+const REGION_WIDTH: usize = 8;
+
+impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Write out our state into the `.mir` files.
+    pub(crate) fn dump_mir(&self, out: &mut Write) -> io::Result<()> {
+        writeln!(out, "| Free Region Mapping")?;
+
+        for region in self.regions() {
+            if self.definitions[region].is_universal {
+                let classification = self.universal_regions.region_classification(region).unwrap();
+                let outlived_by = self.universal_regions.regions_outlived_by(region);
+                writeln!(
+                    out,
+                    "| {r:rw$} | {c:cw$} | {ob}",
+                    r = format!("{:?}", region),
+                    rw = REGION_WIDTH,
+                    c = format!("{:?}", classification),
+                    cw = 8, // "External" at most
+                    ob = format!("{:?}", outlived_by)
+                )?;
+            }
+        }
+
+        writeln!(out, "|")?;
+        writeln!(out, "| Inferred Region Values")?;
+        for region in self.regions() {
+            writeln!(
+                out,
+                "| {r:rw$} | {v}",
+                r = format!("{:?}", region),
+                rw = REGION_WIDTH,
+                v = self.region_value_str(region),
+            )?;
+        }
+
+        writeln!(out, "|")?;
+        writeln!(out, "| Inference Constraints")?;
+        self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?;
+
+        Ok(())
+    }
+
+    /// Debugging aid: Invokes the `with_msg` callback repeatedly with
+    /// our internal region constraints.  These are dumped into the
+    /// -Zdump-mir file so that we can figure out why the region
+    /// inference resulted in the values that it did when debugging.
+    fn for_each_constraint(
+        &self,
+        with_msg: &mut FnMut(&str) -> io::Result<()>,
+    ) -> io::Result<()> {
+        for region in self.definitions.indices() {
+            let value = self.region_value_str_from_matrix(&self.liveness_constraints, region);
+            if value != "{}" {
+                with_msg(&format!("{:?} live at {}", region, value))?;
+            }
+        }
+
+        let mut constraints: Vec<_> = self.constraints.iter().collect();
+        constraints.sort();
+        for constraint in &constraints {
+            let Constraint {
+                sup,
+                sub,
+                point,
+                span,
+            } = constraint;
+            with_msg(&format!(
+                "{:?}: {:?} @ {:?} due to {:?}",
+                sup,
+                sub,
+                point,
+                span
+            ))?;
+        }
+
+        Ok(())
+    }
+}
+
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
new file mode 100644
index 00000000000..7923b159d80
--- /dev/null
+++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
@@ -0,0 +1,71 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This module provides linkage between RegionInferenceContext and
+//! libgraphviz traits, specialized to attaching borrowck analysis
+//! data to rendered labels.
+
+use dot::{self, IntoCow};
+use rustc_data_structures::indexed_vec::Idx;
+use std::borrow::Cow;
+use std::io::{self, Write};
+use super::*;
+
+impl<'tcx> RegionInferenceContext<'tcx> {
+    /// Write out the region constraint graph.
+    pub(crate) fn dump_graphviz(&self, mut w: &mut Write) -> io::Result<()> {
+        dot::render(self, &mut w)
+    }
+}
+
+impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> {
+    type Node = RegionVid;
+    type Edge = Constraint;
+
+    fn graph_id(&'this self) -> dot::Id<'this> {
+        dot::Id::new(format!("RegionInferenceContext")).unwrap()
+    }
+    fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> {
+        dot::Id::new(format!("r{}", n.index())).unwrap()
+    }
+    fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
+        Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
+    }
+    fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
+        dot::LabelText::LabelStr(format!("{:?}", n).into_cow())
+    }
+    fn edge_label(&'this self, e: &Constraint) -> dot::LabelText<'this> {
+        dot::LabelText::LabelStr(format!("{:?}", e.point).into_cow())
+    }
+}
+
+impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> {
+    type Node = RegionVid;
+    type Edge = Constraint;
+
+    fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
+        let vids: Vec<RegionVid> = self.definitions.indices().collect();
+        vids.into_cow()
+    }
+    fn edges(&'this self) -> dot::Edges<'this, Constraint> {
+        (&self.constraints[..]).into_cow()
+    }
+
+    // Render `a: b` as `a <- b`, indicating the flow
+    // of data during inference.
+
+    fn source(&'this self, edge: &Constraint) -> RegionVid {
+        edge.sub
+    }
+
+    fn target(&'this self, edge: &Constraint) -> RegionVid {
+        edge.sup
+    }
+}
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 d1faaf75a53..b2e2ccc5d0b 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -9,12 +9,13 @@
 // except according to those terms.
 
 use super::universal_regions::UniversalRegions;
+use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
-use rustc::infer::RegionVariableOrigin;
 use rustc::infer::NLLRegionVariableOrigin;
+use rustc::infer::RegionVariableOrigin;
+use rustc::infer::SubregionOrigin;
 use rustc::infer::region_constraints::VarOrigins;
-use rustc::infer::outlives::free_region_map::FreeRegionMap;
-use rustc::mir::{Location, Mir};
+use rustc::mir::{ClosureOutlivesRequirement, ClosureRegionRequirements, Location, Mir};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashSet;
@@ -24,6 +25,10 @@ use std::collections::BTreeMap;
 use std::fmt;
 use syntax_pos::Span;
 
+mod annotation;
+mod dump_mir;
+mod graphviz;
+
 pub struct RegionInferenceContext<'tcx> {
     /// Contains the definition for every region variable.  Region
     /// variables are identified by their index (`RegionVid`). The
@@ -52,12 +57,9 @@ pub struct RegionInferenceContext<'tcx> {
     /// the free regions.)
     point_indices: BTreeMap<Location, usize>,
 
-    /// Number of universally quantified regions. This is used to
-    /// determine the meaning of the bits in `inferred_values` and
-    /// friends.
-    num_universal_regions: usize,
-
-    free_region_map: &'tcx FreeRegionMap<'tcx>,
+    /// Information about the universally quantified regions in scope
+    /// on this function and their (known) relations to one another.
+    universal_regions: UniversalRegions<'tcx>,
 }
 
 struct RegionDefinition<'tcx> {
@@ -67,9 +69,15 @@ struct RegionDefinition<'tcx> {
     /// late-bound-regions).
     origin: RegionVariableOrigin,
 
-    /// If this is a free-region, then this is `Some(X)` where `X` is
-    /// the name of the region.
-    name: Option<ty::Region<'tcx>>,
+    /// True if this is a universally quantified region. This means a
+    /// lifetime parameter that appears in the function signature (or,
+    /// in the case of a closure, in the closure environment, which of
+    /// course is also in the function signature).
+    is_universal: bool,
+
+    /// If this is 'static or an early-bound region, then this is
+    /// `Some(X)` where `X` is the name of the region.
+    external_name: Option<ty::Region<'tcx>>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -98,11 +106,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// regions defined in `universal_regions`.
     pub fn new(
         var_origins: VarOrigins,
-        universal_regions: &UniversalRegions<'tcx>,
+        universal_regions: UniversalRegions<'tcx>,
         mir: &Mir<'tcx>,
     ) -> Self {
         let num_region_variables = var_origins.len();
-        let num_universal_regions = universal_regions.indices.len();
+        let num_universal_regions = universal_regions.len();
 
         let mut num_points = 0;
         let mut point_indices = BTreeMap::new();
@@ -133,11 +141,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             inferred_values: None,
             constraints: Vec::new(),
             point_indices,
-            num_universal_regions,
-            free_region_map: universal_regions.free_region_map,
+            universal_regions,
         };
 
-        result.init_universal_regions(universal_regions);
+        result.init_universal_regions();
 
         result
     }
@@ -159,25 +166,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///     R1 = { CFG, R0, R1 } // 'b
     ///
     /// Here, R0 represents `'a`, and it contains (a) the entire CFG
-    /// and (b) any free regions that it outlives, which in this case
-    /// is just itself. R1 (`'b`) in contrast also outlives `'a` and
-    /// hence contains R0 and R1.
-    fn init_universal_regions(&mut self, universal_regions: &UniversalRegions<'tcx>) {
-        let UniversalRegions {
-            indices,
-            free_region_map: _,
-        } = universal_regions;
+    /// and (b) any universally quantified regions that it outlives,
+    /// which in this case is just itself. R1 (`'b`) in contrast also
+    /// outlives `'a` and hence contains R0 and R1.
+    fn init_universal_regions(&mut self) {
+        // Update the names (if any)
+        for (external_name, variable) in self.universal_regions.named_universal_regions() {
+            self.definitions[variable].external_name = Some(external_name);
+        }
 
         // For each universally quantified region X:
-        for (free_region, &variable) in indices {
+        for variable in self.universal_regions.universal_regions() {
             // These should be free-region variables.
             assert!(match self.definitions[variable].origin {
                 RegionVariableOrigin::NLL(NLLRegionVariableOrigin::FreeRegion) => true,
                 _ => false,
             });
 
-            // Initialize the name and a few other details.
-            self.definitions[variable].name = Some(free_region);
+            self.definitions[variable].is_universal = true;
 
             // Add all nodes in the CFG to liveness constraints
             for (_location, point_index) in &self.point_indices {
@@ -196,6 +202,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         self.definitions.indices()
     }
 
+    /// Given a universal region in scope on the MIR, returns the
+    /// corresponding index.
+    ///
+    /// (Panics if `r` is not a registered universal region.)
+    pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
+        self.universal_regions.to_region_vid(r)
+    }
+
     /// Returns true if the region `r` contains the point `p`.
     ///
     /// Panics if called before `solve()` executes,
@@ -237,19 +251,25 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .as_ref()
             .expect("region values not yet inferred");
 
+        self.region_value_str_from_matrix(inferred_values, r)
+    }
+
+    fn region_value_str_from_matrix(&self,
+                                    matrix: &BitMatrix,
+                                    r: RegionVid) -> String {
         let mut result = String::new();
         result.push_str("{");
         let mut sep = "";
 
         for &point in self.point_indices.keys() {
-            if self.region_contains_point_in_matrix(inferred_values, r, point) {
+            if self.region_contains_point_in_matrix(matrix, r, point) {
                 result.push_str(&format!("{}{:?}", sep, point));
                 sep = ", ";
             }
         }
 
-        for fr in (0..self.num_universal_regions).map(RegionVid::new) {
-            if self.region_contains_region_in_matrix(inferred_values, r, fr) {
+        for fr in (0..self.universal_regions.len()).map(RegionVid::new) {
+            if self.region_contains_region_in_matrix(matrix, r, fr) {
                 result.push_str(&format!("{}{:?}", sep, fr));
                 sep = ", ";
             }
@@ -289,8 +309,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     /// Perform region inference.
-    pub(super) fn solve(&mut self, infcx: &InferCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) {
+    pub(super) fn solve(
+        &mut self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        mir: &Mir<'tcx>,
+        mir_def_id: DefId,
+    ) -> Option<ClosureRegionRequirements> {
         assert!(self.inferred_values.is_none(), "values already inferred");
+        let tcx = infcx.tcx;
 
         // Find the minimal regions that can solve the constraints. This is infallible.
         self.propagate_constraints(mir);
@@ -310,57 +336,135 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // The universal regions are always found in a prefix of the
         // full list.
-        let free_region_definitions = self.definitions
+        let universal_definitions = self.definitions
             .iter_enumerated()
-            .take_while(|(_, fr_definition)| fr_definition.name.is_some());
+            .take_while(|(_, fr_definition)| fr_definition.is_universal);
+
+        // Go through each of the universal regions `fr` and check that
+        // they did not grow too large, accumulating any requirements
+        // for our caller into the `outlives_requirements` vector.
+        let mut outlives_requirements = vec![];
+        for (fr, _) in universal_definitions {
+            self.check_universal_region(infcx, fr, &mut outlives_requirements);
+        }
 
-        for (fr, fr_definition) in free_region_definitions {
-            self.check_free_region(infcx, fr, fr_definition);
+        // If this is not a closure, then there is no caller to which we can
+        // "pass the buck". So if there are any outlives-requirements that were
+        // not satisfied, we just have to report a hard error here.
+        if !tcx.is_closure(mir_def_id) {
+            for outlives_requirement in outlives_requirements {
+                self.report_error(
+                    infcx,
+                    outlives_requirement.free_region,
+                    outlives_requirement.outlived_free_region,
+                    outlives_requirement.blame_span,
+                );
+            }
+            return None;
         }
+
+        let num_external_vids = self.universal_regions.num_global_and_external_regions();
+
+        Some(ClosureRegionRequirements {
+            num_external_vids,
+            outlives_requirements,
+        })
     }
 
-    fn check_free_region(
+    /// Check the final value for the free region `fr` to see if it
+    /// grew too large. In particular, examine what `end(X)` points
+    /// wound up in `fr`'s final value; for each `end(X)` where `X !=
+    /// fr`, we want to check that `fr: X`. If not, that's either an
+    /// error, or something we have to propagate to our creator.
+    ///
+    /// Things that are to be propagated are accumulated into the
+    /// `outlives_requirements` vector.
+    fn check_universal_region(
         &self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
         longer_fr: RegionVid,
-        longer_definition: &RegionDefinition<'tcx>,
+        outlives_requirements: &mut Vec<ClosureOutlivesRequirement>,
     ) {
         let inferred_values = self.inferred_values.as_ref().unwrap();
-        let longer_name = longer_definition.name.unwrap();
         let longer_value = inferred_values.iter(longer_fr.index());
 
-        // Find every region `shorter` such that `longer: shorter`
-        // (because `longer` includes `end(shorter)`).
-        for shorter_fr in longer_value.take_while(|&i| i < self.num_universal_regions) {
-            let shorter_fr = RegionVid::new(shorter_fr);
+        debug!("check_universal_region(fr={:?})", longer_fr);
 
-            // `fr` includes `end(fr)`, that's not especially
-            // interesting.
-            if longer_fr == shorter_fr {
+        // Find every region `o` such that `fr: o`
+        // (because `fr` includes `end(o)`).
+        let shorter_frs = longer_value
+            .take_while(|&i| i < self.universal_regions.len())
+            .map(RegionVid::new);
+        for shorter_fr in shorter_frs {
+            // If it is known that `fr: o`, carry on.
+            if self.universal_regions.outlives(longer_fr, shorter_fr) {
                 continue;
             }
 
-            let shorter_definition = &self.definitions[shorter_fr];
-            let shorter_name = shorter_definition.name.unwrap();
-
-            // Check that `o <= fr`. If not, report an error.
-            if !self.free_region_map
-                .sub_free_regions(shorter_name, longer_name)
-            {
-                // FIXME: worst error msg ever
-                let blame_span = self.blame_span(longer_fr, shorter_fr);
-                infcx.tcx.sess.span_err(
-                    blame_span,
-                    &format!(
-                        "free region `{}` does not outlive `{}`",
-                        longer_name,
-                        shorter_name
-                    ),
+            debug!(
+                "check_universal_region: fr={:?} does not outlive shorter_fr={:?}",
+                longer_fr,
+                shorter_fr,
+            );
+
+            let blame_span = self.blame_span(longer_fr, shorter_fr);
+
+            // Shrink `fr` until we find a non-local region (if we do).
+            // We'll call that `fr-` -- it's ever so slightly smaller than `fr`.
+            if let Some(fr_minus) = self.universal_regions.non_local_lower_bound(longer_fr) {
+                debug!("check_universal_region: fr_minus={:?}", fr_minus);
+
+                // Grow `shorter_fr` until we find a non-local
+                // regon. (We always will.)  We'll call that
+                // `shorter_fr+` -- it's ever so slightly larger than
+                // `fr`.
+                let shorter_fr_plus = self.universal_regions.non_local_upper_bound(shorter_fr);
+                debug!(
+                    "check_universal_region: shorter_fr_plus={:?}",
+                    shorter_fr_plus
                 );
+
+                // Push the constraint `fr-: shorter_fr+`
+                outlives_requirements.push(ClosureOutlivesRequirement {
+                    free_region: fr_minus,
+                    outlived_free_region: shorter_fr_plus,
+                    blame_span: blame_span,
+                });
+                return;
             }
+
+            // If we could not shrink `fr` to something smaller that
+            // the external users care about, then we can't pass the
+            // buck; just report an error.
+            self.report_error(infcx, longer_fr, shorter_fr, blame_span);
         }
     }
 
+    fn report_error(
+        &self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        fr: RegionVid,
+        outlived_fr: RegionVid,
+        blame_span: Span,
+    ) {
+        // Obviously uncool error reporting.
+
+        let fr_string = match self.definitions[fr].external_name {
+            Some(r) => format!("free region `{}`", r),
+            None => format!("free region `{:?}`", fr),
+        };
+
+        let outlived_fr_string = match self.definitions[outlived_fr].external_name {
+            Some(r) => format!("free region `{}`", r),
+            None => format!("free region `{:?}`", outlived_fr),
+        };
+
+        infcx.tcx.sess.span_err(
+            blame_span,
+            &format!("{} does not outlive {}", fr_string, outlived_fr_string,),
+        );
+    }
+
     /// Propagate the region constraints: this will grow the values
     /// for each region variable until all the constraints are
     /// satisfied. Note that some values may grow **too** large to be
@@ -421,8 +525,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         stack.push(start_point);
         while let Some(p) = stack.pop() {
-            debug!("        copy: p={:?}", p);
-
             if !self.region_contains_point_in_matrix(inferred_values, from_region, p) {
                 debug!("            not in from-region");
                 continue;
@@ -464,7 +566,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // and make sure they are included in the `to_region`.
                 let universal_region_indices = inferred_values
                     .iter(from_region.index())
-                    .take_while(|&i| i < self.num_universal_regions)
+                    .take_while(|&i| i < self.universal_regions.len())
                     .collect::<Vec<_>>();
                 for fr in &universal_region_indices {
                     changed |= inferred_values.add(to_region.index(), *fr);
@@ -535,7 +637,11 @@ impl<'tcx> RegionDefinition<'tcx> {
         // Create a new region definition. Note that, for free
         // regions, these fields get updated later in
         // `init_universal_regions`.
-        Self { origin, name: None }
+        Self {
+            origin,
+            is_universal: false,
+            external_name: None,
+        }
     }
 }
 
@@ -551,3 +657,70 @@ impl fmt::Debug for Constraint {
         )
     }
 }
+
+pub trait ClosureRegionRequirementsExt {
+    fn apply_requirements<'tcx>(
+        &self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        location: Location,
+        closure_def_id: DefId,
+        closure_substs: ty::ClosureSubsts<'tcx>,
+    );
+}
+
+impl ClosureRegionRequirementsExt for ClosureRegionRequirements {
+    /// Given an instance T of the closure type, this method
+    /// instantiates the "extra" requirements that we computed for the
+    /// closure into the inference context. This has the effect of
+    /// adding new subregion obligations to existing variables.
+    ///
+    /// As described on `ClosureRegionRequirements`, the extra
+    /// requirements are expressed in terms of regionvids that index
+    /// into the free regions that appear on the closure type. So, to
+    /// do this, we first copy those regions out from the type T into
+    /// a vector. Then we can just index into that vector to extract
+    /// out the corresponding region from T and apply the
+    /// requirements.
+    fn apply_requirements<'tcx>(
+        &self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        location: Location,
+        closure_def_id: DefId,
+        closure_substs: ty::ClosureSubsts<'tcx>,
+    ) {
+        let tcx = infcx.tcx;
+
+        debug!(
+            "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
+            location,
+            closure_def_id,
+            closure_substs
+        );
+
+        // Get Tu.
+        let user_closure_ty = tcx.mk_closure(closure_def_id, closure_substs);
+        debug!("apply_requirements: user_closure_ty={:?}", user_closure_ty);
+
+        // Extract the values of the free regions in `user_closure_ty`
+        // into a vector.  These are the regions that we will be
+        // relating to one another.
+        let closure_mapping =
+            UniversalRegions::closure_mapping(infcx, user_closure_ty, self.num_external_vids);
+        debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
+
+        // Create the predicates.
+        for outlives_requirement in &self.outlives_requirements {
+            let region = closure_mapping[outlives_requirement.free_region];
+            let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
+            debug!(
+                "apply_requirements: region={:?} outlived_region={:?} outlives_requirements={:?}",
+                region,
+                outlived_region,
+                outlives_requirement
+            );
+            // FIXME, this origin is not entirely suitable.
+            let origin = SubregionOrigin::CallRcvr(outlives_requirement.blame_span);
+            infcx.sub_regions(origin, outlived_region, region);
+        }
+    }
+}
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 371419da024..1262c238a13 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::indexed_vec::Idx;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, ClosureSubsts, RegionVid, Ty, TypeFoldable};
+use rustc::ty::{self, ClosureSubsts, Ty, TypeFoldable};
 use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
+use rustc::mir::RETURN_PLACE;
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
@@ -25,25 +26,24 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
     universal_regions: &UniversalRegions<'tcx>,
     mir: &mut Mir<'tcx>,
 ) {
-    // Create inference variables for each of the free regions
-    // declared on the function signature.
-    let free_region_inference_vars = (0..universal_regions.indices.len())
-        .map(RegionVid::new)
-        .map(|vid_expected| {
-            let r = infcx.next_nll_region_var(NLLRegionVariableOrigin::FreeRegion);
-            assert_eq!(vid_expected, r.to_region_vid());
-            r
-        })
-        .collect();
-
     debug!("renumber_mir()");
-    debug!("renumber_mir: universal_regions={:#?}", universal_regions);
     debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);
 
+    // Update the return type and types of the arguments based on the
+    // `universal_regions` computation.
+    debug!("renumber_mir: output_ty={:?}", universal_regions.output_ty);
+    mir.local_decls[RETURN_PLACE].ty = universal_regions.output_ty;
+    for (&input_ty, local) in universal_regions
+        .input_tys
+        .iter()
+        .zip((1..).map(Local::new))
+    {
+        debug!("renumber_mir: input_ty={:?} local={:?}", input_ty, local);
+        mir.local_decls[local].ty = input_ty;
+    }
+
     let mut visitor = NLLVisitor {
         infcx,
-        universal_regions,
-        free_region_inference_vars,
         arg_count: mir.arg_count,
     };
     visitor.visit_mir(mir);
@@ -51,8 +51,6 @@ pub fn renumber_mir<'a, 'gcx, 'tcx>(
 
 struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    universal_regions: &'a UniversalRegions<'tcx>,
-    free_region_inference_vars: IndexVec<RegionVid, ty::Region<'tcx>>,
     arg_count: usize,
 }
 
@@ -74,20 +72,17 @@ impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
             })
     }
 
-    /// Renumbers the regions appearing in `value`, but those regions
-    /// are expected to be free regions from the function signature.
-    fn renumber_universal_regions<T>(&mut self, value: &T) -> T
+    /// Checks that all the regions appearing in `value` have already
+    /// been renumbered. `FreeRegions` code should have done this.
+    fn assert_free_regions_are_renumbered<T>(&self, value: &T)
     where
         T: TypeFoldable<'tcx>,
     {
-        debug!("renumber_universal_regions(value={:?})", value);
+        debug!("assert_free_regions_are_renumbered(value={:?})", value);
 
-        self.infcx
-            .tcx
-            .fold_regions(value, &mut false, |region, _depth| {
-                let index = self.universal_regions.indices[&region];
-                self.free_region_inference_vars[index]
-            })
+        self.infcx.tcx.for_each_free_region(value, |region| {
+            region.to_region_vid(); // will panic if `region` is not renumbered
+        });
     }
 
     fn is_argument_or_return_slot(&self, local: Local) -> bool {
@@ -110,12 +105,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
             ty_context
         );
 
-        let old_ty = *ty;
-        *ty = if is_arg {
-            self.renumber_universal_regions(&old_ty)
+        if is_arg {
+            self.assert_free_regions_are_renumbered(ty);
         } else {
-            self.renumber_regions(ty_context, &old_ty)
-        };
+            *ty = self.renumber_regions(ty_context, ty);
+        }
+
         debug!("visit_ty: ty={:?}", ty);
     }
 
@@ -138,6 +133,11 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
         debug!("visit_region: region={:?}", region);
     }
 
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Location) {
+        let ty_context = TyContext::Location(location);
+        *constant = self.renumber_regions(ty_context, &*constant);
+    }
+
     fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
         debug!(
             "visit_closure_substs(substs={:?}, location={:?})",
diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
index dbae40be6fe..c98a94fa8bc 100644
--- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs
@@ -15,7 +15,6 @@ use rustc::ty;
 use transform::type_check::MirTypeckRegionConstraints;
 use transform::type_check::OutlivesSet;
 
-use super::universal_regions::UniversalRegions;
 use super::region_infer::RegionInferenceContext;
 
 /// When the MIR type-checker executes, it validates all the types in
@@ -25,20 +24,17 @@ use super::region_infer::RegionInferenceContext;
 /// them into the NLL `RegionInferenceContext`.
 pub(super) fn generate<'tcx>(
     regioncx: &mut RegionInferenceContext<'tcx>,
-    universal_regions: &UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
     constraints: &MirTypeckRegionConstraints<'tcx>,
 ) {
     SubtypeConstraintGenerator {
         regioncx,
-        universal_regions,
         mir,
     }.generate(constraints);
 }
 
 struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> {
     regioncx: &'cx mut RegionInferenceContext<'tcx>,
-    universal_regions: &'cx UniversalRegions<'tcx>,
     mir: &'cx Mir<'tcx>,
 }
 
@@ -106,7 +102,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> {
         if let ty::ReVar(vid) = r {
             *vid
         } else {
-            self.universal_regions.indices[&r]
+            self.regioncx.to_region_vid(r)
         }
     }
 }
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index 3be95a114c3..857a620cead 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -22,69 +22,681 @@
 //! The code in this file doesn't *do anything* with those results; it
 //! just returns them for other code to use.
 
+use rustc::hir::HirId;
 use rustc::hir::def_id::DefId;
-use rustc::infer::InferCtxt;
-use rustc::infer::outlives::free_region_map::FreeRegionMap;
-use rustc::ty::{self, RegionVid};
+use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
+use rustc::infer::region_constraints::GenericKind;
+use rustc::infer::outlives::bounds::{self, OutlivesBound};
+use rustc::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::FxHashMap;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::transitive_relation::TransitiveRelation;
+use std::iter;
+use syntax::ast;
+
+use super::ToRegionVid;
 
 #[derive(Debug)]
 pub struct UniversalRegions<'tcx> {
-    /// Given a universally quantified region defined on this function
-    /// (either early- or late-bound), this maps it to its internal
-    /// region index. When the region context is created, the first N
-    /// variables will be created based on these indices.
-    pub indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
-
-    /// The map from the typeck tables telling us how to relate universal regions.
-    pub free_region_map: &'tcx FreeRegionMap<'tcx>,
+    indices: UniversalRegionIndices<'tcx>,
+
+    /// The vid assigned to `'static`
+    pub fr_static: RegionVid,
+
+    /// We create region variables such that they are ordered by their
+    /// `RegionClassification`. The first block are globals, then
+    /// externals, then locals. So things from:
+    /// - `FIRST_GLOBAL_INDEX..first_extern_index` are global;
+    /// - `first_extern_index..first_local_index` are external; and
+    /// - first_local_index..num_universals` are local.
+    first_extern_index: usize,
+
+    /// See `first_extern_index`.
+    first_local_index: usize,
+
+    /// The total number of universal region variables instantiated.
+    num_universals: usize,
+
+    /// The "defining" type for this function, with all universal
+    /// regions instantiated.  For a closure or generator, this is the
+    /// closure type, but for a top-level function it's the `TyFnDef`.
+    pub defining_ty: Ty<'tcx>,
+
+    /// The return type of this function, with all regions replaced
+    /// by their universal `RegionVid` equivalents.
+    pub output_ty: Ty<'tcx>,
+
+    /// The fully liberated input types of this function, with all
+    /// regions replaced by their universal `RegionVid` equivalents.
+    pub input_tys: &'tcx [Ty<'tcx>],
+
+    /// Each RBP `('a, GK)` indicates that `GK: 'a` can be assumed to
+    /// be true. These encode relationships like `T: 'a` that are
+    /// added via implicit bounds.
+    ///
+    /// Each region here is guaranteed to be a key in the `indices`
+    /// map.  We use the "original" regions (i.e., the keys from the
+    /// map, and not the values) because the code in
+    /// `process_registered_region_obligations` has some special-cased
+    /// logic expecting to see (e.g.) `ReStatic`, and if we supplied
+    /// our special inference variable there, we would mess that up.
+    pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
+
+    relations: UniversalRegionRelations,
+}
+
+#[derive(Debug)]
+struct UniversalRegionIndices<'tcx> {
+    /// For those regions that may appear in the parameter environment
+    /// ('static and early-bound regions), we maintain a map from the
+    /// `ty::Region` to the internal `RegionVid` we are using. This is
+    /// used because trait matching and type-checking will feed us
+    /// region constraints that reference those regions and we need to
+    /// be able to map them our internal `RegionVid`. This is
+    /// basically equivalent to a `Substs`, except that it also
+    /// contains an entry for `ReStatic` -- it might be nice to just
+    /// use a substs, and then handle `ReStatic` another way.
+    indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
+}
+
+#[derive(Debug)]
+struct UniversalRegionRelations {
+    /// Stores the outlives relations that are known to hold from the
+    /// implied bounds, in-scope where clauses, and that sort of
+    /// thing.
+    outlives: TransitiveRelation<RegionVid>,
+
+    /// This is the `<=` relation; that is, if `a: b`, then `b <= a`,
+    /// and we store that here. This is useful when figuring out how
+    /// to express some local region in terms of external regions our
+    /// caller will understand.
+    inverse_outlives: TransitiveRelation<RegionVid>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum RegionClassification {
+    /// A **global** region is one that can be named from
+    /// anywhere. There is only one, `'static`.
+    Global,
+
+    /// An **external** region is only relevant for closures. In that
+    /// case, it refers to regions that are free in the closure type
+    /// -- basically, something bound in the surrounding context.
+    ///
+    /// Consider this example:
+    ///
+    /// ```
+    /// fn foo<'a, 'b>(a: &'a u32, b: &'b u32, c: &'static u32) {
+    ///   let closure = for<'x> |x: &'x u32| { .. };
+    ///                 ^^^^^^^ pretend this were legal syntax
+    ///                         for declaring a late-bound region in
+    ///                         a closure signature
+    /// }
+    /// ```
+    ///
+    /// Here, the lifetimes `'a` and `'b` would be **external** to the
+    /// closure.
+    ///
+    /// If we are not analyzing a closure, there are no external
+    /// lifetimes.
+    External,
+
+    /// A **local** lifetime is one about which we know the full set
+    /// of relevant constraints (that is, relationships to other named
+    /// regions).  For a closure, this includes any region bound in
+    /// the closure's signature.  For a fn item, this includes all
+    /// regions other than global ones.
+    ///
+    /// Continuing with the example from `External`, if we were
+    /// analyzing the closure, then `'x` would be local (and `'a` and
+    /// `'b` are external).  If we are analyzing the function item
+    /// `foo`, then `'a` and `'b` are local (and `'x` is not in
+    /// scope).
+    Local,
 }
 
-pub fn universal_regions<'a, 'gcx, 'tcx>(
-    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    item_def_id: DefId,
-) -> UniversalRegions<'tcx> {
-    debug!("universal_regions(item_def_id={:?})", item_def_id);
+const FIRST_GLOBAL_INDEX: usize = 0;
+
+impl<'tcx> UniversalRegions<'tcx> {
+    /// Creates a new and fully initialized `UniversalRegions` that
+    /// contains indices for all the free regions found in the given
+    /// MIR -- that is, all the regions that appear in the function's
+    /// signature. This will also compute the relationships that are
+    /// known between those regions.
+    pub fn new(
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        mir_def_id: DefId,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Self {
+        let tcx = infcx.tcx;
+        let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).unwrap();
+        let mir_hir_id = tcx.hir.node_to_hir_id(mir_node_id);
+        UniversalRegionsBuilder {
+            infcx,
+            mir_def_id,
+            mir_node_id,
+            mir_hir_id,
+            param_env,
+            region_bound_pairs: vec![],
+            relations: UniversalRegionRelations {
+                outlives: TransitiveRelation::new(),
+                inverse_outlives: TransitiveRelation::new(),
+            },
+        }.build()
+    }
+
+    /// Given a reference to a closure type, extracts all the values
+    /// from its free regions and returns a vector with them. This is
+    /// used when the closure's creator checks that the
+    /// `ClosureRegionRequirements` are met. The requirements from
+    /// `ClosureRegionRequirements` are expressed in terms of
+    /// `RegionVid` entries that map into the returned vector `V`: so
+    /// if the `ClosureRegionRequirements` contains something like
+    /// `'1: '2`, then the caller would impose the constraint that
+    /// `V[1]: V[2]`.
+    pub fn closure_mapping(
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        closure_ty: Ty<'tcx>,
+        expected_num_vars: usize,
+    ) -> IndexVec<RegionVid, ty::Region<'tcx>> {
+        let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
+        region_mapping.push(infcx.tcx.types.re_static);
+        infcx.tcx.for_each_free_region(&closure_ty, |fr| {
+            region_mapping.push(fr);
+        });
+
+        assert_eq!(
+            region_mapping.len(),
+            expected_num_vars,
+            "index vec had unexpected number of variables"
+        );
 
-    let mut indices = FxHashMap();
+        region_mapping
+    }
 
-    // `'static` is always free.
-    insert_free_region(&mut indices, infcx.tcx.types.re_static);
+    /// True if `r` is a member of this set of universal regions.
+    pub fn is_universal_region(&self, r: RegionVid) -> bool {
+        (FIRST_GLOBAL_INDEX..self.num_universals).contains(r.index())
+    }
 
-    // Extract the early regions.
-    let item_substs = Substs::identity_for_item(infcx.tcx, item_def_id);
-    for item_subst in item_substs {
-        if let Some(region) = item_subst.as_region() {
-            insert_free_region(&mut indices, region);
+    /// Classifies `r` as a universal region, returning `None` if this
+    /// is not a member of this set of universal regions.
+    pub fn region_classification(&self, r: RegionVid) -> Option<RegionClassification> {
+        let index = r.index();
+        if (FIRST_GLOBAL_INDEX..self.first_extern_index).contains(index) {
+            Some(RegionClassification::Global)
+        } else if (self.first_extern_index..self.first_local_index).contains(index) {
+            Some(RegionClassification::External)
+        } else if (self.first_local_index..self.num_universals).contains(index) {
+            Some(RegionClassification::Local)
+        } else {
+            None
         }
     }
 
-    // Extract the late-bound regions. Use the liberated fn sigs,
-    // where the late-bound regions will have been converted into free
-    // regions, and add them to the map.
-    let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap();
-    let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
-    let tables = infcx.tcx.typeck_tables_of(item_def_id);
-    let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
-    infcx
-        .tcx
-        .for_each_free_region(&fn_sig.inputs_and_output, |region| {
-            if let ty::ReFree(_) = *region {
-                insert_free_region(&mut indices, region);
+    /// Returns an iterator over all the RegionVids corresponding to
+    /// universally quantified free regions.
+    pub fn universal_regions(&self) -> impl Iterator<Item = RegionVid> {
+        (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new)
+    }
+
+    /// True if `r` is classied as a global region.
+    pub fn is_global_free_region(&self, r: RegionVid) -> bool {
+        self.region_classification(r) == Some(RegionClassification::Global)
+    }
+
+    /// True if `r` is classied as an external region.
+    pub fn is_extern_free_region(&self, r: RegionVid) -> bool {
+        self.region_classification(r) == Some(RegionClassification::External)
+    }
+
+    /// True if `r` is classied as an local region.
+    pub fn is_local_free_region(&self, r: RegionVid) -> bool {
+        self.region_classification(r) == Some(RegionClassification::Local)
+    }
+
+    /// Returns the number of universal regions created in any category.
+    pub fn len(&self) -> usize {
+        self.num_universals
+    }
+
+    /// Finds an "upper bound" for `fr` that is not local. In other
+    /// words, returns the smallest (*) known region `fr1` that (a)
+    /// outlives `fr` and (b) is not local. This cannot fail, because
+    /// we will always find `'static` at worst.
+    ///
+    /// (*) If there are multiple competing choices, we pick the "postdominating"
+    /// one. See `TransitiveRelation::postdom_upper_bound` for details.
+    pub fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
+        debug!("non_local_upper_bound(fr={:?})", fr);
+        self.non_local_bound(&self.relations.inverse_outlives, fr)
+            .unwrap_or(self.fr_static)
+    }
+
+    /// Finds a "lower bound" for `fr` that is not local. In other
+    /// words, returns the largest (*) known region `fr1` that (a) is
+    /// outlived by `fr` and (b) is not local. This cannot fail,
+    /// because we will always find `'static` at worst.
+    ///
+    /// (*) If there are multiple competing choices, we pick the "postdominating"
+    /// one. See `TransitiveRelation::postdom_upper_bound` for details.
+    pub fn non_local_lower_bound(&self, fr: RegionVid) -> Option<RegionVid> {
+        debug!("non_local_lower_bound(fr={:?})", fr);
+        self.non_local_bound(&self.relations.outlives, fr)
+    }
+
+    /// Returns the number of global plus external universal regions.
+    /// For closures, these are the regions that appear free in the
+    /// closure type (versus those bound in the closure
+    /// signature). They are therefore the regions between which the
+    /// closure may impose constraints that its creator must verify.
+    pub fn num_global_and_external_regions(&self) -> usize {
+        self.first_local_index
+    }
+
+    /// Helper for `non_local_upper_bound` and
+    /// `non_local_lower_bound`.  Repeatedly invokes `postdom_parent`
+    /// until we find something that is not local. Returns None if we
+    /// never do so.
+    fn non_local_bound(
+        &self,
+        relation: &TransitiveRelation<RegionVid>,
+        fr0: RegionVid,
+    ) -> Option<RegionVid> {
+        let mut external_parents = vec![];
+        let mut queue = vec![&fr0];
+
+        // Keep expanding `fr` into its parents until we reach
+        // non-local regions.
+        while let Some(fr) = queue.pop() {
+            if !self.is_local_free_region(*fr) {
+                external_parents.push(fr);
+                continue;
             }
-        });
 
-    debug!("universal_regions: indices={:#?}", indices);
+            queue.extend(relation.parents(fr));
+        }
+
+        debug!("non_local_bound: external_parents={:?}", external_parents);
+
+        // In case we find more than one, reduce to one for
+        // convenience.  This is to prevent us from generating more
+        // complex constraints, but it will cause spurious errors.
+        let post_dom = relation
+            .mutual_immediate_postdominator(external_parents)
+            .cloned();
+
+        debug!("non_local_bound: post_dom={:?}", post_dom);
+
+        post_dom.and_then(|post_dom| {
+            // If the mutual immediate postdom is not local, then
+            // there is no non-local result we can return.
+            if !self.is_local_free_region(post_dom) {
+                Some(post_dom)
+            } else {
+                None
+            }
+        })
+    }
+
+    /// True if fr1 is known to outlive fr2.
+    ///
+    /// This will only ever be true for universally quantified regions.
+    pub fn outlives(&self, fr1: RegionVid, fr2: RegionVid) -> bool {
+        self.relations.outlives.contains(&fr1, &fr2)
+    }
+
+    /// Returns a vector of free regions `x` such that `fr1: x` is
+    /// known to hold.
+    pub fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<&RegionVid> {
+        self.relations.outlives.reachable_from(&fr1)
+    }
+
+    /// Get an iterator over all the early-bound regions that have names.
+    pub fn named_universal_regions<'s>(
+        &'s self,
+    ) -> impl Iterator<Item = (ty::Region<'tcx>, ty::RegionVid)> + 's {
+        self.indices.indices.iter().map(|(&r, &v)| (r, v))
+    }
+
+    /// See `UniversalRegionIndices::to_region_vid`.
+    pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
+        self.indices.to_region_vid(r)
+    }
+}
+
+struct UniversalRegionsBuilder<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+    mir_def_id: DefId,
+    mir_hir_id: HirId,
+    mir_node_id: ast::NodeId,
+    param_env: ty::ParamEnv<'tcx>,
+    region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
+    relations: UniversalRegionRelations,
+}
+
+const FR: NLLRegionVariableOrigin = NLLRegionVariableOrigin::FreeRegion;
+
+impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> {
+    fn build(mut self) -> UniversalRegions<'tcx> {
+        debug!("build(mir_def_id={:?})", self.mir_def_id);
+
+        let param_env = self.param_env;
+        debug!("build: param_env={:?}", param_env);
+
+        assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
+
+        // Create the "global" region that is always free in all contexts: 'static.
+        let fr_static = self.infcx.next_nll_region_var(FR).to_region_vid();
+
+        // We've now added all the global regions. The next ones we
+        // add will be external.
+        let first_extern_index = self.infcx.num_region_vars();
+
+        let defining_ty = self.defining_ty();
+        debug!("build: defining_ty={:?}", defining_ty);
+
+        let indices = self.compute_indices(fr_static, defining_ty);
+        debug!("build: indices={:?}", indices);
+
+        let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
+
+        // "Liberate" the late-bound regions. These correspond to
+        // "local" free regions.
+        let first_local_index = self.infcx.num_region_vars();
+        let inputs_and_output = self.infcx
+            .replace_bound_regions_with_nll_infer_vars(FR, &bound_inputs_and_output);
+        let num_universals = self.infcx.num_region_vars();
+
+        // Insert the facts we know from the predicates. Why? Why not.
+        self.add_outlives_bounds(&indices, bounds::explicit_outlives_bounds(param_env));
+
+        // Add the implied bounds from inputs and outputs.
+        for ty in inputs_and_output {
+            debug!("build: input_or_output={:?}", ty);
+            self.add_implied_bounds(&indices, ty);
+        }
+
+        // Finally, outlives is reflexive, and static outlives every
+        // other free region.
+        for fr in (FIRST_GLOBAL_INDEX..num_universals).map(RegionVid::new) {
+            debug!("build: relating free region {:?} to itself and to 'static", fr);
+            self.relations.relate_universal_regions(fr, fr);
+            self.relations.relate_universal_regions(fr_static, fr);
+        }
+
+        let (output_ty, input_tys) = inputs_and_output.split_last().unwrap();
+
+        // we should not have created any more variables
+        assert_eq!(self.infcx.num_region_vars(), num_universals);
+
+        debug!("build: global regions = {}..{}",
+               FIRST_GLOBAL_INDEX,
+               first_extern_index);
+        debug!("build: extern regions = {}..{}",
+               first_extern_index,
+               first_local_index);
+        debug!("build: local regions  = {}..{}",
+               first_local_index,
+               num_universals);
+
+        UniversalRegions {
+            indices,
+            fr_static,
+            first_extern_index,
+            first_local_index,
+            num_universals,
+            defining_ty,
+            output_ty,
+            input_tys,
+            region_bound_pairs: self.region_bound_pairs,
+            relations: self.relations,
+        }
+    }
+
+    fn defining_ty(&self) -> ty::Ty<'tcx> {
+        let tcx = self.infcx.tcx;
+        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
+
+        let defining_ty = if self.mir_def_id == closure_base_def_id {
+            tcx.type_of(closure_base_def_id)
+        } else {
+            let tables = tcx.typeck_tables_of(self.mir_def_id);
+            tables.node_id_to_type(self.mir_hir_id)
+        };
+
+        self.infcx
+            .replace_free_regions_with_nll_infer_vars(FR, &defining_ty)
+    }
+
+    fn compute_indices(
+        &self,
+        fr_static: RegionVid,
+        defining_ty: Ty<'tcx>,
+    ) -> UniversalRegionIndices<'tcx> {
+        let tcx = self.infcx.tcx;
+        let gcx = tcx.global_tcx();
+        let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
+        let identity_substs = Substs::identity_for_item(gcx, closure_base_def_id);
+        let fr_substs = match defining_ty.sty {
+            ty::TyClosure(_, substs) | ty::TyGenerator(_, substs, ..) => {
+                // In the case of closures, we rely on the fact that
+                // the first N elements in the ClosureSubsts are
+                // inherited from the `closure_base_def_id`.
+                // Therefore, when we zip together (below) with
+                // `identity_substs`, we will get only those regions
+                // that correspond to early-bound regions declared on
+                // the `closure_base_def_id`.
+                assert!(substs.substs.len() >= identity_substs.len());
+                substs.substs
+            }
+            ty::TyFnDef(_, substs) => substs,
+            _ => bug!(),
+        };
+
+        let global_mapping = iter::once((gcx.types.re_static, fr_static));
+        let subst_mapping = identity_substs
+            .regions()
+            .zip(fr_substs.regions().map(|r| r.to_region_vid()));
+
+        UniversalRegionIndices {
+            indices: global_mapping.chain(subst_mapping).collect(),
+        }
+    }
+
+    fn compute_inputs_and_output(
+        &self,
+        indices: &UniversalRegionIndices<'tcx>,
+        defining_ty: Ty<'tcx>,
+    ) -> ty::Binder<&'tcx ty::Slice<Ty<'tcx>>> {
+        let tcx = self.infcx.tcx;
+        match defining_ty.sty {
+            ty::TyClosure(def_id, substs) => {
+                assert_eq!(self.mir_def_id, def_id);
+                let closure_sig = substs.closure_sig_ty(def_id, tcx).fn_sig(tcx);
+                let inputs_and_output = closure_sig.inputs_and_output();
+                let closure_ty = tcx.closure_env_ty(def_id, substs).unwrap();
+                ty::Binder::fuse(
+                    closure_ty,
+                    inputs_and_output,
+                    |closure_ty, inputs_and_output| {
+                        // The "inputs" of the closure in the
+                        // signature appear as a tuple.  The MIR side
+                        // flattens this tuple.
+                        let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap();
+                        assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs");
+                        let inputs = match tuplized_inputs[0].sty {
+                            ty::TyTuple(inputs, _) => inputs,
+                            _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]),
+                        };
 
-    UniversalRegions { indices, free_region_map: &tables.free_region_map }
+                        tcx.mk_type_list(
+                            iter::once(closure_ty)
+                                .chain(inputs.iter().cloned())
+                                .chain(iter::once(output)),
+                        )
+                    },
+                )
+            }
+
+            ty::TyGenerator(def_id, substs, ..) => {
+                assert_eq!(self.mir_def_id, def_id);
+                let output = substs.generator_return_ty(def_id, tcx);
+                let inputs_and_output = self.infcx.tcx.intern_type_list(&[defining_ty, output]);
+                ty::Binder::dummy(inputs_and_output)
+            }
+
+            ty::TyFnDef(def_id, _) => {
+                let sig = tcx.fn_sig(def_id);
+                let sig = indices.fold_to_region_vids(tcx, &sig);
+                return sig.inputs_and_output();
+            }
+
+            _ => span_bug!(
+                tcx.def_span(self.mir_def_id),
+                "unexpected defining type: {:?}",
+                defining_ty
+            ),
+        }
+    }
+
+    /// Update the type of a single local, which should represent
+    /// 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.
+    ///
+    /// Assumes that `universal_regions` indices map is fully constructed.
+    fn add_implied_bounds(&mut self, indices: &UniversalRegionIndices<'tcx>, ty: Ty<'tcx>) {
+        debug!("add_implied_bounds(ty={:?})", ty);
+        let span = self.infcx.tcx.def_span(self.mir_def_id);
+        let bounds = self.infcx
+            .implied_outlives_bounds(self.param_env, self.mir_node_id, ty, span);
+        self.add_outlives_bounds(indices, bounds);
+    }
+
+    /// Registers the `OutlivesBound` items from `outlives_bounds` in
+    /// the outlives relation as well as the region-bound pairs
+    /// listing.
+    fn add_outlives_bounds<I>(&mut self, indices: &UniversalRegionIndices<'tcx>, outlives_bounds: I)
+    where
+        I: IntoIterator<Item = OutlivesBound<'tcx>>,
+    {
+        for outlives_bound in outlives_bounds {
+            debug!("add_outlives_bounds(bound={:?})", outlives_bound);
+
+            match outlives_bound {
+                OutlivesBound::RegionSubRegion(r1, r2) => {
+                    // The bound says that `r1 <= r2`; we store `r2: r1`.
+                    let r1 = indices.to_region_vid(r1);
+                    let r2 = indices.to_region_vid(r2);
+                    self.relations.relate_universal_regions(r2, r1);
+                }
+
+                OutlivesBound::RegionSubParam(r_a, param_b) => {
+                    self.region_bound_pairs
+                        .push((r_a, GenericKind::Param(param_b)));
+                }
+
+                OutlivesBound::RegionSubProjection(r_a, projection_b) => {
+                    self.region_bound_pairs
+                        .push((r_a, GenericKind::Projection(projection_b)));
+                }
+            }
+        }
+    }
+}
+
+impl UniversalRegionRelations {
+    /// Records in the `outlives_relation` (and
+    /// `inverse_outlives_relation`) that `fr_a: fr_b`.
+    fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
+        debug!(
+            "relate_universal_regions: fr_a={:?} outlives fr_b={:?}",
+            fr_a,
+            fr_b
+        );
+        self.outlives.add(fr_a, fr_b);
+        self.inverse_outlives.add(fr_b, fr_a);
+    }
+}
+
+pub(crate) trait InferCtxtExt<'tcx> {
+    fn replace_free_regions_with_nll_infer_vars<T>(
+        &self,
+        origin: NLLRegionVariableOrigin,
+        value: &T,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>;
+
+    fn replace_bound_regions_with_nll_infer_vars<T>(
+        &self,
+        origin: NLLRegionVariableOrigin,
+        value: &ty::Binder<T>,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>;
+}
+
+impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> {
+    fn replace_free_regions_with_nll_infer_vars<T>(
+        &self,
+        origin: NLLRegionVariableOrigin,
+        value: &T,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.tcx.fold_regions(
+            value,
+            &mut false,
+            |_region, _depth| self.next_nll_region_var(origin),
+        )
+    }
+
+    fn replace_bound_regions_with_nll_infer_vars<T>(
+        &self,
+        origin: NLLRegionVariableOrigin,
+        value: &ty::Binder<T>,
+    ) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        let (value, _map) = self.tcx
+            .replace_late_bound_regions(value, |_br| self.next_nll_region_var(origin));
+        value
+    }
 }
 
-fn insert_free_region<'tcx>(
-    universal_regions: &mut FxHashMap<ty::Region<'tcx>, RegionVid>,
-    region: ty::Region<'tcx>,
-) {
-    let next = RegionVid::new(universal_regions.len());
-    universal_regions.entry(region).or_insert(next);
+impl<'tcx> UniversalRegionIndices<'tcx> {
+    /// Converts `r` into a local inference variable: `r` can either
+    /// by a `ReVar` (i.e., already a reference to an inference
+    /// variable) or it can be `'static` or some early-bound
+    /// region. This is useful when taking the results from
+    /// type-checking and trait-matching, which may sometimes
+    /// reference those regions from the `ParamEnv`. It is also used
+    /// during initialization. Relies on the `indices` map having been
+    /// fully initialized.
+    pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
+        match r {
+            ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(),
+            ty::ReVar(..) => r.to_region_vid(),
+            _ => bug!("cannot convert `{:?}` to a region vid", r),
+        }
+    }
+
+    /// Replace all free regions in `value` with region vids, as
+    /// returned by `to_region_vid`.
+    pub fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'_, '_, 'tcx>, value: &T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        tcx.fold_regions(
+            value,
+            &mut false,
+            |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))),
+        )
+    }
 }
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs
index d1bb1f39e22..932aad0bb1d 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir/build/cfg.rs
@@ -51,6 +51,17 @@ impl<'tcx> CFG<'tcx> {
                                              source_info: SourceInfo,
                                              region_scope: region::Scope) {
         if tcx.sess.emit_end_regions() {
+            if let region::ScopeData::CallSite(_) = region_scope.data() {
+                // The CallSite scope (aka the root scope) is sort of weird, in that it is
+                // supposed to "separate" the "interior" and "exterior" of a closure. Being
+                // that, it is not really a part of the region hierarchy, but for some
+                // reason it *is* considered a part of it.
+                //
+                // It should die a hopefully painful death with NLL, so let's leave this hack
+                // for now so that nobody can complain about soundness.
+                return
+            }
+
             self.push(block, Statement {
                 source_info,
                 kind: StatementKind::EndRegion(region_scope),
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 2bba3e263f3..c27cb43eff7 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc::middle::region;
 use rustc::mir::{self, Location, Mir};
 use rustc::mir::visit::Visitor;
 use rustc::ty::{self, Region, TyCtxt};
@@ -27,6 +30,7 @@ use borrow_check::nll::ToRegionVid;
 use syntax_pos::Span;
 
 use std::fmt;
+use std::rc::Rc;
 
 // `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
 // uniquely identified in the MIR by the `Location` of the assigment
@@ -34,9 +38,12 @@ use std::fmt;
 pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    scope_tree: Rc<region::ScopeTree>,
+    root_scope: Option<region::Scope>,
     borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+    local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
     region_span_map: FxHashMap<RegionKind, Span>,
     nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
 }
@@ -69,22 +76,32 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
 impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>)
+               nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
+               def_id: DefId,
+               body_id: Option<hir::BodyId>)
                -> Self {
+        let scope_tree = tcx.region_scope_tree(def_id);
+        let root_scope = body_id.map(|body_id| {
+            region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id)
+        });
         let mut visitor = GatherBorrows {
             tcx,
             mir,
             idx_vec: IndexVec::new(),
             location_map: FxHashMap(),
             region_map: FxHashMap(),
+            local_map: FxHashMap(),
             region_span_map: FxHashMap()
         };
         visitor.visit_mir(mir);
         return Borrows { tcx: tcx,
                          mir: mir,
                          borrows: visitor.idx_vec,
+                         scope_tree,
+                         root_scope,
                          location_map: visitor.location_map,
                          region_map: visitor.region_map,
+                         local_map: visitor.local_map,
                          region_span_map: visitor.region_span_map,
                          nonlexical_regioncx };
 
@@ -94,6 +111,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
             location_map: FxHashMap<Location, BorrowIndex>,
             region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+            local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
             region_span_map: FxHashMap<RegionKind, Span>,
         }
 
@@ -101,6 +119,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             fn visit_rvalue(&mut self,
                             rvalue: &mir::Rvalue<'tcx>,
                             location: mir::Location) {
+                fn root_local(mut p: &mir::Place<'_>) -> Option<mir::Local> {
+                    loop { match p {
+                        mir::Place::Projection(pi) => p = &pi.base,
+                        mir::Place::Static(_) => return None,
+                        mir::Place::Local(l) => return Some(*l)
+                    }}
+                }
+
                 if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
                     if is_unsafe_place(self.tcx, self.mir, place) { return; }
 
@@ -109,8 +135,14 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                     };
                     let idx = self.idx_vec.push(borrow);
                     self.location_map.insert(location, idx);
+
                     let borrows = self.region_map.entry(region).or_insert(FxHashSet());
                     borrows.insert(idx);
+
+                    if let Some(local) = root_local(place) {
+                        let borrows = self.local_map.entry(local).or_insert(FxHashSet());
+                        borrows.insert(idx);
+                    }
                 }
             }
 
@@ -199,7 +231,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::EndRegion(region_scope) => {
                 if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) {
                     assert!(self.nonlexical_regioncx.is_none());
-                    for idx in borrow_indexes { sets.kill(&idx); }
+                    sets.kill_all(borrow_indexes);
                 } else {
                     // (if there is no entry, then there are no borrows to be tracked)
                 }
@@ -224,10 +256,19 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                 }
             }
 
+            mir::StatementKind::StorageDead(local) => {
+                // Make sure there are no remaining borrows for locals that
+                // are gone out of scope.
+                //
+                // FIXME: expand this to variables that are assigned over.
+                if let Some(borrow_indexes) = self.local_map.get(&local) {
+                    sets.kill_all(borrow_indexes);
+                }
+            }
+
             mir::StatementKind::InlineAsm { .. } |
             mir::StatementKind::SetDiscriminant { .. } |
             mir::StatementKind::StorageLive(..) |
-            mir::StatementKind::StorageDead(..) |
             mir::StatementKind::Validate(..) |
             mir::StatementKind::Nop => {}
 
@@ -253,8 +294,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                 // like unwind paths, we do not always emit `EndRegion` statements, so we
                 // add some kills here as a "backup" and to avoid spurious error messages.
                 for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
-                    if let ReScope(..) = borrow_data.region {
-                        sets.kill(&borrow_index);
+                    if let ReScope(scope) = borrow_data.region {
+                        // Check that the scope is not actually a scope from a function that is
+                        // a parent of our closure. Note that the CallSite scope itself is
+                        // *outside* of the closure, for some weird reason.
+                        if let Some(root_scope) = self.root_scope {
+                            if *scope != root_scope &&
+                                self.scope_tree.is_subscope_of(*scope, root_scope)
+                            {
+                                sets.kill(&borrow_index);
+                            }
+                        }
                     }
                 }
             }
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 50c8df3c2e3..db8ca0628c4 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -14,7 +14,6 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
 use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
@@ -504,7 +503,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
         let stmt = &mir[location.block].statements[location.statement_index];
         let loc_map = &move_data.loc_map;
         let path_map = &move_data.path_map;
-        let bits_per_block = self.bits_per_block();
 
         match stmt.kind {
             // this analysis only tries to find moves explicitly
@@ -515,21 +513,15 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
             _ => {
                 debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
                        stmt, location, &loc_map[location]);
-                for move_index in &loc_map[location] {
-                    // Every path deinitialized by a *particular move*
-                    // has corresponding bit, "gen'ed" (i.e. set)
-                    // here, in dataflow vector
-                    zero_to_one(sets.gen_set.words_mut(), *move_index);
-                }
+                // Every path deinitialized by a *particular move*
+                // has corresponding bit, "gen'ed" (i.e. set)
+                // here, in dataflow vector
+                sets.gen_all_and_assert_dead(&loc_map[location]);
             }
         }
 
         for_location_inits(tcx, mir, move_data, location,
-            |mpi| for moi in &path_map[mpi] {
-                assert!(moi.index() < bits_per_block);
-                sets.kill_set.add(&moi);
-            }
-        );
+                           |mpi| sets.kill_all(&path_map[mpi]));
     }
 
     fn terminator_effect(&self,
@@ -543,18 +535,10 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> {
 
         debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
                term, location, &loc_map[location]);
-        let bits_per_block = self.bits_per_block();
-        for move_index in &loc_map[location] {
-            assert!(move_index.index() < bits_per_block);
-            zero_to_one(sets.gen_set.words_mut(), *move_index);
-        }
+        sets.gen_all_and_assert_dead(&loc_map[location]);
 
         for_location_inits(tcx, mir, move_data, location,
-            |mpi| for moi in &path_map[mpi] {
-                assert!(moi.index() < bits_per_block);
-                sets.kill_set.add(&moi);
-            }
-        );
+                           |mpi| sets.kill_all(&path_map[mpi]));
     }
 
     fn propagate_call_return(&self,
@@ -585,11 +569,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
     }
 
     fn start_block_effect(&self, sets: &mut BlockSets<InitIndex>) {
-        let bits_per_block = self.bits_per_block();
-        for init_index in (0..self.mir.arg_count).map(InitIndex::new) {
-            assert!(init_index.index() < bits_per_block);
-            sets.gen_set.add(&init_index);
-        }
+        sets.gen_all((0..self.mir.arg_count).map(InitIndex::new));
     }
     fn statement_effect(&self,
                         sets: &mut BlockSets<InitIndex>,
@@ -599,26 +579,39 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
         let init_path_map = &move_data.init_path_map;
         let init_loc_map = &move_data.init_loc_map;
         let rev_lookup = &move_data.rev_lookup;
-        let bits_per_block = self.bits_per_block();
 
         debug!("statement {:?} at loc {:?} initializes move_indexes {:?}",
                stmt, location, &init_loc_map[location]);
-        for init_index in &init_loc_map[location] {
-            assert!(init_index.index() < bits_per_block);
-            sets.gen_set.add(init_index);
-        }
+        sets.gen_all(&init_loc_map[location]);
 
         match stmt.kind {
-            mir::StatementKind::StorageDead(local) => {
-                // End inits for StorageDead, so that an immutable variable can
-                // be reinitialized on the next iteration of the loop.
+            mir::StatementKind::StorageDead(local) |
+            mir::StatementKind::StorageLive(local) => {
+                // End inits for StorageDead and StorageLive, so that an immutable
+                // variable can be reinitialized on the next iteration of the loop.
+                //
+                // FIXME(#46525): We *need* to do this for StorageLive as well as
+                // StorageDead, because lifetimes of match bindings with guards are
+                // weird - i.e. this code
+                //
+                // ```
+                //     fn main() {
+                //         match 0 {
+                //             a | a
+                //             if { println!("a={}", a); false } => {}
+                //             _ => {}
+                //         }
+                //     }
+                // ```
+                //
+                // runs the guard twice, using the same binding for `a`, and only
+                // storagedeads after everything ends, so if we don't regard the
+                // storagelive as killing storage, we would have a multiple assignment
+                // to immutable data error.
                 if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) {
                     debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
-                        stmt, location, &init_path_map[mpi]);
-                    for ii in &init_path_map[mpi] {
-                        assert!(ii.index() < bits_per_block);
-                        sets.kill_set.add(&ii);
-                    }
+                           stmt, location, &init_path_map[mpi]);
+                    sets.kill_all(&init_path_map[mpi]);
                 }
             }
             _ => {}
@@ -634,13 +627,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
         let init_loc_map = &move_data.init_loc_map;
         debug!("terminator {:?} at loc {:?} initializes move_indexes {:?}",
                term, location, &init_loc_map[location]);
-        let bits_per_block = self.bits_per_block();
-        for init_index in &init_loc_map[location] {
-            if move_data.inits[*init_index].kind != InitKind::NonPanicPathOnly {
-                assert!(init_index.index() < bits_per_block);
-                sets.gen_set.add(init_index);
-            }
-        }
+        sets.gen_all(
+            init_loc_map[location].iter().filter(|init_index| {
+                move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
+            })
+        );
     }
 
     fn propagate_call_return(&self,
@@ -663,11 +654,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> {
     }
 }
 
-fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) {
-    let retval = bitvec.set_bit(move_index.index());
-    assert!(retval);
-}
-
 impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 6be006b1ea9..12722979706 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -18,6 +18,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
 use rustc::session::Session;
 
+use std::borrow::Borrow;
 use std::fmt::{self, Debug};
 use std::io;
 use std::mem;
@@ -492,10 +493,39 @@ impl<'a, E:Idx> BlockSets<'a, E> {
         self.gen_set.add(e);
         self.kill_set.remove(e);
     }
+    fn gen_all<I>(&mut self, i: I)
+        where I: IntoIterator,
+              I::Item: Borrow<E>
+    {
+        for j in i {
+            self.gen(j.borrow());
+        }
+    }
+
+    fn gen_all_and_assert_dead<I>(&mut self, i: I)
+        where I: IntoIterator,
+        I::Item: Borrow<E>
+    {
+        for j in i {
+            let j = j.borrow();
+            let retval = self.gen_set.add(j);
+            self.kill_set.remove(j);
+            assert!(retval);
+        }
+    }
+
     fn kill(&mut self, e: &E) {
         self.gen_set.remove(e);
         self.kill_set.add(e);
     }
+    fn kill_all<I>(&mut self, i: I)
+        where I: IntoIterator,
+              I::Item: Borrow<E>
+    {
+        for j in i {
+            self.kill(j.borrow());
+        }
+    }
 }
 
 impl<E:Idx> AllSets<E> {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index b9b86dd6e84..2b2323928ef 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -41,6 +41,9 @@ use transform::{MirPass, MirSource};
 use super::promote_consts::{self, Candidate, TempState};
 
 bitflags! {
+    // Borrows of temporaries can be promoted only if
+    // they have none of these qualifications, with
+    // the exception of `STATIC_REF` (in statics only).
     struct Qualif: u8 {
         // Constant containing interior mutability (UnsafeCell).
         const MUTABLE_INTERIOR  = 1 << 0;
@@ -65,10 +68,6 @@ bitflags! {
         // promote_consts decided they weren't simple enough.
         const NOT_PROMOTABLE    = 1 << 6;
 
-        // Borrows of temporaries can be promoted only
-        // if they have none of the above qualifications.
-        const NEVER_PROMOTE     = 0b111_1111;
-
         // Const items can only have MUTABLE_INTERIOR
         // and NOT_PROMOTABLE without producing an error.
         const CONST_ERROR       = !Qualif::MUTABLE_INTERIOR.bits &
@@ -197,7 +196,17 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
         self.add(original);
     }
 
-    /// Check if an Place with the current qualifications could
+    /// Check if a Local with the current qualifications is promotable.
+    fn can_promote(&mut self) -> bool {
+        // References to statics are allowed, but only in other statics.
+        if self.mode == Mode::Static || self.mode == Mode::StaticMut {
+            (self.qualif - Qualif::STATIC_REF).is_empty()
+        } else {
+            self.qualif.is_empty()
+        }
+    }
+
+    /// Check if a Place with the current qualifications could
     /// be consumed, by either an operand or a Deref projection.
     fn try_consume(&mut self) -> bool {
         if self.qualif.intersects(Qualif::STATIC) && self.mode != Mode::Fn {
@@ -633,7 +642,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
 
                 // We might have a candidate for promotion.
                 let candidate = Candidate::Ref(location);
-                if !self.qualif.intersects(Qualif::NEVER_PROMOTE) {
+                if self.can_promote() {
                     // We can only promote direct borrows of temps.
                     if let Place::Local(local) = *place {
                         if self.mir.local_kind(local) == LocalKind::Temp {
@@ -745,7 +754,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     this.visit_operand(arg, location);
                     if is_shuffle && i == 2 && this.mode == Mode::Fn {
                         let candidate = Candidate::ShuffleIndices(bb);
-                        if !this.qualif.intersects(Qualif::NEVER_PROMOTE) {
+                        if this.can_promote() {
                             this.promotion_candidates.push(candidate);
                         } else {
                             span_err!(this.tcx.sess, this.span, E0526,
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index f0b62e28a0d..1a74f327001 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -11,6 +11,7 @@
 //! This pass type-checks the MIR to ensure it is not broken.
 #![allow(unreachable_code)]
 
+use borrow_check::nll::region_infer::ClosureRegionRequirementsExt;
 use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
 use rustc::infer::region_constraints::RegionConstraintData;
 use rustc::traits::{self, FulfillmentContext};
@@ -110,6 +111,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
 
     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
         self.super_constant(constant, location);
+        self.sanitize_constant(constant, location);
         self.sanitize_type(constant, constant.ty);
     }
 
@@ -159,6 +161,52 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         }
     }
 
+    /// Checks that the constant's `ty` field matches up with what
+    /// would be expected from its literal.
+    fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
+        debug!(
+            "sanitize_constant(constant={:?}, location={:?})",
+            constant,
+            location
+        );
+
+        let expected_ty = match constant.literal {
+            Literal::Value { value } => value.ty,
+            Literal::Promoted { .. } => {
+                // FIXME -- promoted MIR return types reference
+                // various "free regions" (e.g., scopes and things)
+                // that they ought not to do. We have to figure out
+                // how best to handle that -- probably we want treat
+                // promoted MIR much like closures, renumbering all
+                // their free regions and propagating constraints
+                // upwards. We have the same acyclic guarantees, so
+                // that should be possible. But for now, ignore them.
+                //
+                // let promoted_mir = &self.mir.promoted[index];
+                // promoted_mir.return_ty()
+                return;
+            }
+        };
+
+        debug!("sanitize_constant: expected_ty={:?}", expected_ty);
+
+        if let Err(terr) = self.cx
+            .eq_types(expected_ty, constant.ty, location.at_self())
+        {
+            span_mirbug!(
+                self,
+                constant,
+                "constant {:?} should have type {:?} but has {:?} ({:?})",
+                constant,
+                expected_ty,
+                constant.ty,
+                terr,
+            );
+        }
+    }
+
+    /// Checks that the types internal to the `place` match up with
+    /// what would be expected.
     fn sanitize_place(
         &mut self,
         place: &Place<'tcx>,
@@ -1088,14 +1136,45 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         operands: &[Operand<'tcx>],
         location: Location,
     ) {
+        let tcx = self.tcx();
+
         match aggregate_kind {
             // tuple rvalue field type is always the type of the op. Nothing to check here.
             AggregateKind::Tuple => return,
+
+            // For closures, we have some **extra requirements** we
+            // have to check. In particular, in their upvars and
+            // signatures, closures often reference various regions
+            // from the surrounding function -- we call those the
+            // closure's free regions. When we borrow-check (and hence
+            // region-check) closures, we may find that the closure
+            // requires certain relationships between those free
+            // regions. However, because those free regions refer to
+            // portions of the CFG of their caller, the closure is not
+            // in a position to verify those relationships. In that
+            // case, the requirements get "propagated" to us, and so
+            // we have to solve them here where we instantiate the
+            // closure.
+            //
+            // Despite the opacity of the previous parapgrah, this is
+            // actually relatively easy to understand in terms of the
+            // desugaring. A closure gets desugared to a struct, and
+            // these extra requirements are basically like where
+            // clauses on the struct.
+            AggregateKind::Closure(def_id, substs) => {
+                if let Some(closure_region_requirements) = tcx.mir_borrowck(*def_id) {
+                    closure_region_requirements.apply_requirements(
+                        self.infcx,
+                        location,
+                        *def_id,
+                        *substs,
+                    );
+                }
+            }
+
             _ => {}
         }
 
-        let tcx = self.tcx();
-
         for (i, operand) in operands.iter().enumerate() {
             let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
                 Ok(field_ty) => field_ty,
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 8a3db0eb25b..37f59773cd6 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -11,7 +11,8 @@
 use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::*;
-use rustc::ty::TyCtxt;
+use rustc::mir::visit::Visitor;
+use rustc::ty::{self, TyCtxt};
 use rustc::ty::item_path;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
@@ -56,9 +57,19 @@ pub enum PassWhere {
 /// where `<filter>` takes the following forms:
 ///
 /// - `all` -- dump MIR for all fns, all passes, all everything
-/// - `substring1&substring2,...` -- `&`-separated list of substrings
-///   that can appear in the pass-name or the `item_path_str` for the given
-///   node-id. If any one of the substrings match, the data is dumped out.
+/// - a filter defined by a set of substrings combined with `&` and `|`
+///   (`&` has higher precedence). At least one of the `|`-separated groups
+///   must match; an `|`-separated group matches if all of its `&`-separated
+///   substrings are matched.
+///
+/// Example:
+///
+/// - `nll` == match if `nll` appears in the name
+/// - `foo & nll` == match if `foo` and `nll` both appear in the name
+/// - `foo & nll | typeck` == match if `foo` and `nll` both appear in the name
+///   or `typeck` appears in the name.
+/// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name
+///   or `typeck` and `bar` both appear in the name.
 pub fn dump_mir<'a, 'gcx, 'tcx, F>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     pass_num: Option<&Display>,
@@ -103,8 +114,10 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(
         // see notes on #41697 below
         tcx.item_path_str(source.def_id)
     });
-    filters.split("&").any(|filter| {
-        filter == "all" || pass_name.contains(filter) || node_path.contains(filter)
+    filters.split("|").any(|or_filter| {
+        or_filter.split("&").all(|and_filter| {
+            and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
+        })
     })
 }
 
@@ -125,14 +138,7 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
     F: FnMut(PassWhere, &mut Write) -> io::Result<()>,
 {
     let _: io::Result<()> = do catch {
-        let mut file = create_dump_file(
-            tcx,
-            "mir",
-            pass_num,
-            pass_name,
-            disambiguator,
-            source,
-        )?;
+        let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
         writeln!(file, "// MIR for `{}`", node_path)?;
         writeln!(file, "// source = {:?}", source)?;
         writeln!(file, "// pass_name = {}", pass_name)?;
@@ -148,15 +154,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
     };
 
     if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
-    let _: io::Result<()> = do catch {
-            let mut file = create_dump_file(
-                tcx,
-                "dot",
-                pass_num,
-                pass_name,
-                disambiguator,
-                source,
-            )?;
+        let _: io::Result<()> = do catch {
+            let mut file =
+                create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
             write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
             Ok(())
         };
@@ -297,10 +297,10 @@ where
 }
 
 /// Write out a human-readable textual representation for the given basic block.
-pub fn write_basic_block<F>(
-    tcx: TyCtxt,
+pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
     block: BasicBlock,
-    mir: &Mir,
+    mir: &Mir<'tcx>,
     extra_data: &mut F,
     w: &mut Write,
 ) -> io::Result<()>
@@ -330,6 +330,11 @@ where
             comment(tcx, statement.source_info),
             A = ALIGN,
         )?;
+
+        write_extra(tcx, w, |visitor| {
+            visitor.visit_statement(current_location.block, statement, current_location);
+        })?;
+
         extra_data(PassWhere::AfterLocation(current_location), w)?;
 
         current_location.statement_index += 1;
@@ -346,11 +351,94 @@ where
         comment(tcx, data.terminator().source_info),
         A = ALIGN,
     )?;
+
+    write_extra(tcx, w, |visitor| {
+        visitor.visit_terminator(current_location.block, data.terminator(), current_location);
+    })?;
+
     extra_data(PassWhere::AfterLocation(current_location), w)?;
 
     writeln!(w, "{}}}", INDENT)
 }
 
+/// After we print the main statement, we sometimes dump extra
+/// information. There's often a lot of little things "nuzzled up" in
+/// a statement.
+fn write_extra<'cx, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    write: &mut Write,
+    mut visit_op: F,
+) -> io::Result<()>
+where
+    F: FnMut(&mut ExtraComments<'cx, 'gcx, 'tcx>),
+{
+    let mut extra_comments = ExtraComments {
+        _tcx: tcx,
+        comments: vec![],
+    };
+    visit_op(&mut extra_comments);
+    for comment in extra_comments.comments {
+        writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
+    }
+    Ok(())
+}
+
+struct ExtraComments<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    _tcx: TyCtxt<'cx, 'gcx, 'tcx>, // don't need it now, but bet we will soon
+    comments: Vec<String>,
+}
+
+impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> {
+    fn push(&mut self, lines: &str) {
+        for line in lines.split("\n") {
+            self.comments.push(line.to_string());
+        }
+    }
+}
+
+impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
+    fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
+        self.super_constant(constant, location);
+        let Constant { span, ty, literal } = constant;
+        self.push(&format!("mir::Constant"));
+        self.push(&format!("└ span: {:?}", span));
+        self.push(&format!("└ ty: {:?}", ty));
+        self.push(&format!("└ literal: {:?}", literal));
+    }
+
+    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
+        self.super_const(constant);
+        let ty::Const { ty, val } = constant;
+        self.push(&format!("ty::Const"));
+        self.push(&format!("└ ty: {:?}", ty));
+        self.push(&format!("└ val: {:?}", val));
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
+        match rvalue {
+            Rvalue::Aggregate(kind, _) => match **kind {
+                AggregateKind::Closure(def_id, substs) => {
+                    self.push(&format!("closure"));
+                    self.push(&format!("└ def_id: {:?}", def_id));
+                    self.push(&format!("└ substs: {:#?}", substs));
+                }
+
+                AggregateKind::Generator(def_id, substs, interior) => {
+                    self.push(&format!("generator"));
+                    self.push(&format!("└ def_id: {:?}", def_id));
+                    self.push(&format!("└ substs: {:#?}", substs));
+                    self.push(&format!("└ interior: {:?}", interior));
+                }
+
+                _ => {}
+            },
+
+            _ => {}
+        }
+    }
+}
+
 fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
     format!(
         "scope {} at {}",
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 97cea5c9d64..05ad1643619 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -21,6 +21,7 @@ use rustc::session::Session;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::codemap::Spanned;
+use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
@@ -35,8 +36,16 @@ impl<'a> AstValidator<'a> {
         &self.session.parse_sess.span_diagnostic
     }
 
+    fn check_lifetime(&self, lifetime: &Lifetime) {
+        let valid_names = [keywords::StaticLifetime.name(), keywords::Invalid.name()];
+        if !valid_names.contains(&lifetime.ident.name) &&
+            token::Ident(lifetime.ident.without_first_quote()).is_reserved_ident() {
+            self.err_handler().span_err(lifetime.span, "lifetimes cannot use keyword names");
+        }
+    }
+
     fn check_label(&self, label: Ident, span: Span) {
-        if label.name == keywords::StaticLifetime.name() || label.name == "'_" {
+        if token::Ident(label.without_first_quote()).is_reserved_ident() || label.name == "'_" {
             self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
         }
     }
@@ -200,6 +209,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_use_tree(self, use_tree, id);
     }
 
+    fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
+        self.check_lifetime(lifetime);
+        visit::walk_lifetime(self, lifetime);
+    }
+
     fn visit_item(&mut self, item: &'a Item) {
         match item.node {
             ItemKind::Impl(.., Some(..), _, ref impl_items) => {
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 405647af324..762cf7a0055 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -29,7 +29,7 @@ use value::Value;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{HasDataLayout, LayoutOf};
-use rustc::ty::subst::{Kind, Subst, Substs};
+use rustc::ty::subst::{Kind, Substs};
 use rustc::hir;
 
 use libc::{c_uint, c_char};
@@ -393,7 +393,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
         ty::TyClosure(def_id, substs) => {
             let tcx = ccx.tcx();
-            let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
+            let sig = substs.closure_sig(def_id, tcx);
 
             let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
             sig.map_bound(|sig| tcx.mk_fn_sig(
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index cfca3b57cb9..800c7733c3d 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -74,7 +74,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
         });
         llvm::LLVMSetInitializer(gv, cv);
         set_global_alignment(ccx, gv, align);
-        llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
+        llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
         SetUnnamedAddr(gv, true);
         gv
     }
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 764021983e9..0799a388a8b 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -20,7 +20,7 @@ use rustc::mir::tcx::PlaceTy;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf, Size};
 use rustc::ty::cast::{CastTy, IntTy};
-use rustc::ty::subst::{Kind, Substs, Subst};
+use rustc::ty::subst::{Kind, Substs};
 use rustc_apfloat::{ieee, Float, Status};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use base;
@@ -658,8 +658,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                                     .find(|it| it.kind == ty::AssociatedKind::Method)
                                     .unwrap().def_id;
                                 // Now create its substs [Closure, Tuple]
-                                let input = tcx.fn_sig(def_id)
-                                    .subst(tcx, substs.substs).input(0);
+                                let input = substs.closure_sig(def_id, tcx).input(0);
                                 let input = tcx.erase_late_bound_regions_and_normalize(&input);
                                 let substs = tcx.mk_substs([operand.ty, input]
                                     .iter().cloned().map(Kind::from));
diff --git a/src/librustc_trans_utils/monomorphize.rs b/src/librustc_trans_utils/monomorphize.rs
index 66833a1a7c2..d586d1ac315 100644
--- a/src/librustc_trans_utils/monomorphize.rs
+++ b/src/librustc_trans_utils/monomorphize.rs
@@ -12,7 +12,7 @@ use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::DropInPlaceFnLangItem;
 use rustc::traits;
 use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::ty::subst::{Kind, Subst};
+use rustc::ty::subst::Kind;
 use rustc::ty::{self, Ty, TyCtxt};
 
 pub use rustc::ty::Instance;
@@ -34,7 +34,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let self_ty = tcx.mk_closure_from_closure_substs(
         closure_did, substs);
 
-    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
+    let sig = substs.closure_sig(closure_did, tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 8f409b68752..df1694a6010 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -16,7 +16,6 @@ use hir::def::Def;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::{infer, traits};
 use rustc::ty::{self, TyCtxt, TypeFoldable, LvaluePreference, Ty};
-use rustc::ty::subst::Subst;
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use syntax::abi;
 use syntax::symbol::Symbol;
@@ -109,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id, substs).is_none() {
-                    let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
+                    let closure_ty = self.closure_sig(def_id, substs);
                     let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                    infer::FnCall,
                                                                    &closure_ty)
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 3e725d7ef41..dc5d3141d4c 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -74,7 +74,6 @@ use rustc::ty::{self, LvaluePreference, TypeAndMut,
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::error::TypeError;
 use rustc::ty::relate::RelateResult;
-use rustc::ty::subst::Subst;
 use errors::DiagnosticBuilder;
 use syntax::abi;
 use syntax::feature_gate;
@@ -670,7 +669,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
                 //     `fn(arg0,arg1,...) -> _`
-                let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
+                let sig = self.closure_sig(def_id_a, substs_a);
                 let converted_sig = sig.map_bound(|s| {
                     let params_iter = match s.inputs()[0].sty {
                         ty::TyTuple(params, _) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index b754c981b21..85b926a707d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1268,15 +1268,23 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ))
         }
 
-        NodeExpr(&hir::Expr { node: hir::ExprClosure(..), hir_id, .. }) => {
-            let tables = tcx.typeck_tables_of(def_id);
-            match tables.node_id_to_type(hir_id).sty {
-                ty::TyClosure(closure_def_id, closure_substs) => {
-                    assert_eq!(def_id, closure_def_id);
-                    return closure_substs.closure_sig(closure_def_id, tcx);
-                }
-                ref t => bug!("closure with non-closure type: {:?}", t),
-            }
+        NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
+            // Closure signatures are not like other function
+            // signatures and cannot be accessed through `fn_sig`. For
+            // example, a closure signature excludes the `self`
+            // argument. In any case they are embedded within the
+            // closure type as part of the `ClosureSubsts`.
+            //
+            // To get
+            // the signature of a closure, you should use the
+            // `closure_sig` method on the `ClosureSubsts`:
+            //
+            //    closure_substs.closure_sig(def_id, tcx)
+            //
+            // or, inside of an inference context, you can use
+            //
+            //    infcx.closure_sig(def_id, closure_substs)
+            bug!("to get the signature of a closure, use `closure_sig()` not `fn_sig()`");
         }
 
         x => {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index be7bd3d5510..fbff6e83fb9 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2521,7 +2521,7 @@ pub struct Span {
 }
 
 impl Span {
-    fn empty() -> Span {
+    pub fn empty() -> Span {
         Span {
             filename: "".to_string(),
             loline: 0, locol: 0,
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 8c14d1bbe8f..61de5f4bc4c 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -65,6 +65,7 @@ r##"<!DOCTYPE html>
     {before_content}
 
     <nav class="sidebar">
+        <div class="sidebar-menu">&#9776;</div>
         {logo}
         {sidebar}
     </nav>
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 9dc01bb0916..d423e53ca18 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -421,9 +421,19 @@ impl ToJson for IndexItemFunctionType {
 thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
 thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> =
                     RefCell::new(Vec::new()));
-thread_local!(static USED_ID_MAP: RefCell<FxHashMap<String, usize>> =
+thread_local!(pub static USED_ID_MAP: RefCell<FxHashMap<String, usize>> =
                     RefCell::new(init_ids()));
 
+pub fn render_text<F: FnMut(RenderType) -> String>(mut render: F) -> (String, String) {
+    // Save the state of USED_ID_MAP so it only gets updated once even
+    // though we're rendering twice.
+    let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
+    let hoedown_output = render(RenderType::Hoedown);
+    USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map);
+    let pulldown_output = render(RenderType::Pulldown);
+    (hoedown_output, pulldown_output)
+}
+
 fn init_ids() -> FxHashMap<String, usize> {
     [
      "main",
@@ -699,7 +709,10 @@ fn print_message(msg: &str, intro_msg: &mut bool, span: &Span, text: &str) {
     println!("{}", msg);
 }
 
-fn render_difference(diff: &html_diff::Difference, intro_msg: &mut bool, span: &Span, text: &str) {
+pub fn render_difference(diff: &html_diff::Difference,
+                         intro_msg: &mut bool,
+                         span: &Span,
+                         text: &str) {
     match *diff {
         html_diff::Difference::NodeType { ref elem, ref opposite_elem } => {
             print_message(&format!("    {} Types differ: expected: `{}`, found: `{}`",
@@ -1853,12 +1866,7 @@ fn render_markdown(w: &mut fmt::Formatter,
                    prefix: &str,
                    scx: &SharedContext)
                    -> fmt::Result {
-    // Save the state of USED_ID_MAP so it only gets updated once even
-    // though we're rendering twice.
-    let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
-    let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown));
-    USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map);
-    let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown));
+    let (hoedown_output, pulldown_output) = render_text(|ty| format!("{}", Markdown(md_text, ty)));
     let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
     differences.retain(|s| {
         match *s {
@@ -3542,6 +3550,7 @@ impl<'a> fmt::Display for Sidebar<'a> {
         let cx = self.cx;
         let it = self.item;
         let parentlen = cx.current.len() - if it.is_mod() {1} else {0};
+        let mut should_close = false;
 
         if it.is_struct() || it.is_trait() || it.is_primitive() || it.is_union()
             || it.is_enum() || it.is_mod() || it.is_typedef()
@@ -3575,6 +3584,8 @@ impl<'a> fmt::Display for Sidebar<'a> {
                 }
             }
 
+            write!(fmt, "<div class=\"sidebar-elems\">")?;
+            should_close = true;
             match it.inner {
                 clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?,
                 clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?,
@@ -3625,6 +3636,10 @@ impl<'a> fmt::Display for Sidebar<'a> {
             write!(fmt, "<script defer src=\"{path}sidebar-items.js\"></script>",
                    path = relpath)?;
         }
+        if should_close {
+            // Closes sidebar-elems div.
+            write!(fmt, "</div>")?;
+        }
 
         Ok(())
     }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index dc8ce627638..06e9cbbdf9a 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -106,6 +106,30 @@
         return (elem.offsetParent === null)
     }
 
+    function showSidebar() {
+        var elems = document.getElementsByClassName("sidebar-elems")[0];
+        if (elems) {
+            elems.style.display = "block";
+        }
+        var sidebar = document.getElementsByClassName('sidebar')[0];
+        sidebar.style.position = 'fixed';
+        sidebar.style.width = '100%';
+        sidebar.style.marginLeft = '0';
+        document.getElementsByTagName("body")[0].style.marginTop = '45px';
+    }
+
+    function hideSidebar() {
+        var elems = document.getElementsByClassName("sidebar-elems")[0];
+        if (elems) {
+            elems.style.display = "";
+        }
+        var sidebar = document.getElementsByClassName('sidebar')[0];
+        sidebar.style.position = '';
+        sidebar.style.width = '';
+        sidebar.style.marginLeft = '';
+        document.getElementsByTagName("body")[0].style.marginTop = '';
+    }
+
     // used for special search precedence
     var TY_PRIMITIVE = itemTypes.indexOf("primitive");
 
@@ -119,8 +143,7 @@
             map(function(s) {
                 var pair = s.split("=");
                 params[decodeURIComponent(pair[0])] =
-                    typeof pair[1] === "undefined" ?
-                            null : decodeURIComponent(pair[1]);
+                    typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
             });
         return params;
     }
@@ -131,6 +154,8 @@
     }
 
     function highlightSourceLines(ev) {
+        // If we're in mobile mode, we should add the sidebar in any case.
+        hideSidebar();
         var search = document.getElementById("search");
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
@@ -1460,7 +1485,7 @@
 
     // delayed sidebar rendering.
     function initSidebarItems(items) {
-        var sidebar = document.getElementsByClassName('sidebar')[0];
+        var sidebar = document.getElementsByClassName('sidebar-elems')[0];
         var current = window.sidebarCurrent;
 
         function block(shortty, longty) {
@@ -1822,6 +1847,30 @@
             }
         };
     }
+
+    var params = getQueryStringParams();
+    if (params && params.search) {
+        addClass(document.getElementById("main"), "hidden");
+        var search = document.getElementById("search");
+        removeClass(search, "hidden");
+        search.innerHTML = '<h3 style="text-align: center;">Loading search results...</h3>';
+    }
+
+    var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
+    if (sidebar_menu) {
+        sidebar_menu.onclick = function() {
+            var sidebar = document.getElementsByClassName('sidebar')[0];
+            if (sidebar.style.position === "fixed") {
+                hideSidebar();
+            } else {
+                showSidebar();
+            }
+        };
+    }
+
+    window.onresize = function() {
+        hideSidebar();
+    };
 }());
 
 // Sets the focus on the search bar at the top of the page
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 426405e1812..99a0f8c3fb1 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -208,7 +208,7 @@ nav.sub {
 .sidebar .version {
 	font-size: 15px;
 	text-align: center;
-	border-bottom: #DDDDDD 1px solid;
+	border-bottom: 1px solid;
 	overflow-wrap: break-word;
 	word-wrap: break-word; /* deprecated */
 	word-break: break-word; /* Chrome, non-standard */
@@ -247,8 +247,8 @@ nav.sub {
 }
 
 .sidebar-title {
-	border-top: 1px solid #777;
-	border-bottom: 1px solid #777;
+	border-top: 1px solid;
+	border-bottom: 1px solid;
 	text-align: center;
 	font-size: 17px;
 	margin-bottom: 5px;
@@ -263,6 +263,10 @@ nav.sub {
 	width: 100%;
 }
 
+.sidebar-menu {
+	display: none;
+}
+
 .content {
 	padding: 15px 0;
 }
@@ -364,7 +368,6 @@ h4 > code, h3 > code, .invisible > code {
 }
 
 .invisible {
-	background: rgba(0, 0, 0, 0);
 	width: 100%;
 	display: inline-block;
 }
@@ -444,7 +447,6 @@ h4 > code, h3 > code, .invisible > code {
 .content .fn .where,
 .content .where.fmt-newline {
 	display: block;
-	color: #4E4C4C;
 	font-size: 0.8em;
 }
 
@@ -538,7 +540,6 @@ a {
 }
 
 .search-input:focus {
-	border-color: #66afe9;
 	border-radius: 2px;
 	border: 0;
 	outline: 0;
@@ -560,7 +561,8 @@ a {
 .content .search-results td:first-child a { padding-right: 10px; }
 
 tr.result span.primitive::after {
-	content: ' (primitive type)'; font-style: italic; color: black;
+	content: ' (primitive type)';
+	font-style: italic;
 }
 
 body.blur > :not(#help) {
@@ -697,7 +699,6 @@ a.test-arrow:hover{
 	font-weight: 300;
 	position: absolute;
 	left: -23px;
-	color: #999;
 	top: 0;
 }
 
@@ -823,7 +824,7 @@ span.since {
 		position: static;
 	}
 
-	.sidebar .location {
+	.sidebar > .location {
 		float: right;
 		margin: 0px;
 		margin-top: 2px;
@@ -843,16 +844,33 @@ span.since {
 		margin-top: 5px;
 		margin-bottom: 5px;
 		float: left;
+		margin-left: 50px;
 	}
 
-	nav.sub {
-		margin: 0 auto;
+	.sidebar-menu {
+		position: absolute;
+		font-size: 2rem;
+		cursor: pointer;
+		margin-top: 2px;
+		display: block;
 	}
 
-	.sidebar .block {
+	.sidebar-elems {
+		background-color: #F1F1F1;
+		position: fixed;
+		z-index: 1;
+		left: 0;
+		top: 45px;
+		bottom: 0;
+		overflow-y: auto;
+		border-right: 1px solid #000;
 		display: none;
 	}
 
+	nav.sub {
+		margin: 0 auto;
+	}
+
 	.content {
 		margin-left: 0px;
 	}
@@ -904,8 +922,6 @@ span.since {
 .tooltip .tooltiptext {
 	width: 120px;
 	display: none;
-	background-color: black;
-	color: #fff;
 	text-align: center;
 	padding: 5px 3px;
 	border-radius: 6px;
@@ -927,13 +943,10 @@ span.since {
 	margin-top: -5px;
 	border-width: 5px;
 	border-style: solid;
-	border-color: transparent black transparent transparent;
 }
 
 .important-traits .tooltip .tooltiptext {
-	background-color: white;
-	color: black;
-	border: 1px solid #000;
+	border: 1px solid;
 }
 
 pre.rust {
@@ -953,22 +966,21 @@ pre.rust {
 	float: left;
 	width: 33.3%;
 	text-align: center;
-	border-bottom: 1px solid #ccc;
+	border-bottom: 1px solid;
 	font-size: 18px;
 	cursor: pointer;
 }
 
 #titles > div.selected {
-	border-bottom: 3px solid #0078ee;
+	border-bottom: 3px solid;
 }
 
 #titles > div:hover {
-	border-bottom: 3px solid #0089ff;
+	border-bottom: 3px solid;
 }
 
 #titles > div > div.count {
 	display: inline-block;
-	color: #888;
 	font-size: 16px;
 }
 
@@ -995,7 +1007,6 @@ h4 > .important-traits {
 	position: fixed;
 	width: 100vw;
 	height: 100vh;
-	background-color: rgba(0,0,0,0.3);
 	z-index: 10000;
 	top: 0;
 	left: 0;
@@ -1005,13 +1016,12 @@ h4 > .important-traits {
 	display: block;
 	max-width: 60%;
 	min-width: 200px;
-	background-color: #eee;
 	padding: 8px;
 	top: 40%;
 	position: absolute;
 	left: 50%;
 	transform: translate(-50%, -40%);
-	border: 1px solid #999;
+	border: 1px solid;
 	border-radius: 4px;
 	border-top-right-radius: 0;
 }
@@ -1038,35 +1048,24 @@ h3.important {
 	right: -25px;
 	top: -1px;
 	font-size: 18px;
-	background-color: #eee;
 	width: 25px;
 	padding-right: 2px;
 	border-top-right-radius: 5px;
 	border-bottom-right-radius: 5px;
 	text-align: center;
-	border: 1px solid #999;
+	border: 1px solid;
 	border-right: 0;
 	cursor: pointer;
 }
 
-.modal-content > .close:hover {
-	background-color: #ff1f1f;
-	color: white;
-}
-
 .modal-content > .whiter {
 	height: 25px;
 	position: absolute;
 	width: 3px;
-	background-color: #eee;
 	right: -2px;
 	top: 0px;
 }
 
-.modal-content > .close:hover + .whiter {
-	background-color: #ff1f1f;
-}
-
 #main > div.important-traits {
 	position: absolute;
 	left: -24px;
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css
index cb19034bf06..5cace837a55 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/styles/main.css
@@ -31,6 +31,10 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t
 	background-color: white;
 }
 
+.invisible {
+	background: rgba(0, 0, 0, 0);
+}
+
 .docblock code, .docblock-short code {
 	background-color: #F5F5F5;
 }
@@ -56,6 +60,15 @@ pre {
 	color: #333;
 }
 
+.sidebar .version {
+	border-bottom-color: #DDD;
+}
+
+.sidebar-title {
+	border-top-color: #777;
+	border-bottom-color: #777;
+}
+
 .block a:hover {
 	background: #F5F5F5;
 }
@@ -89,6 +102,12 @@ pre {
 	background: #FDFFD3;
 }
 
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+	color: #4E4C4C;
+}
+
 .content .highlighted {
 	color: #000 !important;
 	background-color: #ccc;
@@ -152,12 +171,20 @@ a.test-arrow {
 	color: #f5f5f5;
 }
 
+.collapse-toggle {
+	color: #999;
+}
+
 .search-input {
 	color: #555;
 	box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
 	background-color: white;
 }
 
+.search-input:focus {
+	border-color: #66afe9;
+}
+
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; }
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
@@ -176,6 +203,10 @@ a.test-arrow {
 	color: grey;
 }
 
+tr.result span.primitive::after {
+	color: black;
+}
+
 .line-numbers :target { background-color: transparent; }
 
 /* Code highlighting */
@@ -241,3 +272,61 @@ pre.ignore:hover, .information:hover + pre.ignore {
 .search-failed > a {
 	color: #0089ff;
 }
+
+.tooltip .tooltiptext {
+	background-color: black;
+	color: #fff;
+}
+
+.tooltip .tooltiptext::after {
+	border-color: transparent black transparent transparent;
+}
+
+.important-traits .tooltip .tooltiptext {
+	background-color: white;
+	color: black;
+	border-color: black;
+}
+
+#titles > div {
+	border-bottom-color:  #ccc;
+}
+
+#titles > div.selected {
+	border-bottom-color: #0078ee;
+}
+
+#titles > div:hover {
+	border-bottom-color: #0089ff;
+}
+
+#titles > div > div.count {
+	color: #888;
+}
+
+.modal {
+	background-color: rgba(0,0,0,0.3);
+}
+
+.modal-content {
+	background-color: #eee;
+	border-color: #999;
+}
+
+.modal-content > .close {
+	background-color: #eee;
+	border-color: #999;
+}
+
+.modal-content > .close:hover {
+	background-color: #ff1f1f;
+	color: white;
+}
+
+.modal-content > .whiter {
+	background-color: #eee;
+}
+
+.modal-content > .close:hover + .whiter {
+	background-color: #ff1f1f;
+}
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index fe6bd985bb6..9b94e9918f8 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -19,10 +19,15 @@ use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::Externs;
 use syntax::codemap::DUMMY_SP;
 
+use clean::Span;
+
 use externalfiles::{ExternalHtml, LoadStringError, load_string};
 
-use html::render::reset_ids;
+use html_diff;
+
+use html::render::{render_text, reset_ids};
 use html::escape::Escape;
+use html::render::render_difference;
 use html::markdown;
 use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code};
 use html::markdown::RenderType;
@@ -52,6 +57,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
 pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
               external_html: &ExternalHtml, include_toc: bool,
               render_type: RenderType) -> isize {
+    // Span used for markdown hoedown/pulldown differences.
+    let mut span = Span::empty();
+    span.filename = input.to_owned();
+
     let input_p = Path::new(input);
     output.push(input_p.file_stem().unwrap());
     output.set_extension("html");
@@ -89,12 +98,36 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 
     reset_ids(false);
 
-    let rendered = if include_toc {
-        format!("{}", MarkdownWithToc(text, render_type))
+    let (hoedown_output, pulldown_output) = if include_toc {
+        // Save the state of USED_ID_MAP so it only gets updated once even
+        // though we're rendering twice.
+        render_text(|ty| format!("{}", MarkdownWithToc(text, ty)))
     } else {
-        format!("{}", Markdown(text, render_type))
+        // Save the state of USED_ID_MAP so it only gets updated once even
+        // though we're rendering twice.
+        render_text(|ty| format!("{}", Markdown(text, ty)))
     };
 
+    let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
+    differences.retain(|s| {
+        match *s {
+            html_diff::Difference::NodeText { ref elem_text,
+                                              ref opposite_elem_text,
+                                              .. }
+                if elem_text.split_whitespace().eq(opposite_elem_text.split_whitespace()) => {
+                    false
+            }
+            _ => true,
+        }
+    });
+
+    if !differences.is_empty() {
+        let mut intro_msg = false;
+        for diff in differences {
+            render_difference(&diff, &mut intro_msg, &span, text);
+        }
+    }
+
     let err = write!(
         &mut out,
         r#"<!DOCTYPE html>
@@ -126,16 +159,16 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
         css = css,
         in_header = external_html.in_header,
         before_content = external_html.before_content,
-        text = rendered,
+        text = if render_type == RenderType::Pulldown { pulldown_output } else { hoedown_output },
         after_content = external_html.after_content,
-        );
+    );
 
     match err {
         Err(e) => {
             eprintln!("rustdoc: cannot write to `{}`: {}", output.display(), e);
             6
         }
-        Ok(_) => 0
+        Ok(_) => 0,
     }
 }
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index b07733d3c80..f40aed2478a 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -211,6 +211,115 @@ pub struct DirBuilder {
     recursive: bool,
 }
 
+/// Read the entire contents of a file into a bytes vector.
+///
+/// This is a convenience function for using [`File::open`] and [`read_to_end`]
+/// with fewer imports and without an intermediate variable.
+///
+/// [`File::open`]: struct.File.html#method.open
+/// [`read_to_end`]: ../io/trait.Read.html#method.read_to_end
+///
+/// # Errors
+///
+/// This function will return an error if `path` does not already exist.
+/// Other errors may also be returned according to [`OpenOptions::open`].
+///
+/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
+///
+/// It will also return an error if it encounters while reading an error
+/// of a kind other than [`ErrorKind::Interrupted`].
+///
+/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(fs_read_write)]
+///
+/// use std::fs;
+/// use std::net::SocketAddr;
+///
+/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
+/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "fs_read_write", issue = "46588")]
+pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
+    let mut bytes = Vec::new();
+    File::open(path)?.read_to_end(&mut bytes)?;
+    Ok(bytes)
+}
+
+/// Read the entire contents of a file into a string.
+///
+/// This is a convenience function for using [`File::open`] and [`read_to_string`]
+/// with fewer imports and without an intermediate variable.
+///
+/// [`File::open`]: struct.File.html#method.open
+/// [`read_to_string`]: ../io/trait.Read.html#method.read_to_string
+///
+/// # Errors
+///
+/// This function will return an error if `path` does not already exist.
+/// Other errors may also be returned according to [`OpenOptions::open`].
+///
+/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
+///
+/// It will also return an error if it encounters while reading an error
+/// of a kind other than [`ErrorKind::Interrupted`],
+/// or if the contents of the file are not valid UTF-8.
+///
+/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(fs_read_write)]
+///
+/// use std::fs;
+/// use std::net::SocketAddr;
+///
+/// # fn foo() -> Result<(), Box<std::error::Error + 'static>> {
+/// let foo: SocketAddr = fs::read_string("address.txt")?.parse()?;
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "fs_read_write", issue = "46588")]
+pub fn read_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
+    let mut string = String::new();
+    File::open(path)?.read_to_string(&mut string)?;
+    Ok(string)
+}
+
+/// Write a slice as the entire contents of a file.
+///
+/// This function will create a file if it does not exist,
+/// and will entirely replace its contents if it does.
+///
+/// This is a convenience function for using [`File::create`] and [`write_all`]
+/// with fewer imports.
+///
+/// [`File::create`]: struct.File.html#method.create
+/// [`write_all`]: ../io/trait.Write.html#method.write_all
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(fs_read_write)]
+///
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// fs::write("foo.txt", b"Lorem ipsum")?;
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "fs_read_write", issue = "46588")]
+pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
+    File::create(path)?.write_all(contents.as_ref())
+}
+
 impl File {
     /// Attempts to open a file in read-only mode.
     ///
@@ -1912,7 +2021,9 @@ mod tests {
     ) }
 
     #[cfg(unix)]
-    macro_rules! error { ($e:expr, $s:expr) => (
+    macro_rules! error { ($e:expr, $s:expr) => ( error_contains!($e, $s) ) }
+
+    macro_rules! error_contains { ($e:expr, $s:expr) => (
         match $e {
             Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
             Err(ref err) => assert!(err.to_string().contains($s),
@@ -2922,6 +3033,27 @@ mod tests {
     }
 
     #[test]
+    fn write_then_read() {
+        let mut bytes = [0; 1024];
+        StdRng::new().unwrap().fill_bytes(&mut bytes);
+
+        let tmpdir = tmpdir();
+
+        check!(fs::write(&tmpdir.join("test"), &bytes[..]));
+        let v = check!(fs::read(&tmpdir.join("test")));
+        assert!(v == &bytes[..]);
+
+        check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF]));
+        error_contains!(fs::read_string(&tmpdir.join("not-utf8")),
+                        "stream did not contain valid UTF-8");
+
+        let s = "𐁁𐀓𐀠𐀴𐀍";
+        check!(fs::write(&tmpdir.join("utf8"), s.as_bytes()));
+        let string = check!(fs::read_string(&tmpdir.join("utf8")));
+        assert_eq!(string, s);
+    }
+
+    #[test]
     fn file_try_clone() {
         let tmpdir = tmpdir();
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index bf177ac7f2c..12e6231136e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -260,6 +260,7 @@
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
+#![feature(fs_read_write)]
 #![feature(fixed_size_array)]
 #![feature(float_from_str_radix)]
 #![feature(fn_traits)]
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index b36473d9b75..de46fedaebb 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -631,7 +631,7 @@ pub mod builtin {
     #[macro_export]
     macro_rules! module_path { () => ({ /* compiler built-in */ }) }
 
-    /// Boolean evaluation of configuration flags.
+    /// Boolean evaluation of configuration flags, at compile-time.
     ///
     /// In addition to the `#[cfg]` attribute, this macro is provided to allow
     /// boolean expression evaluation of configuration flags. This frequently
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index d4b54e896ab..22cef25320e 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -284,10 +284,6 @@ declare_features! (
     // Allows all literals in attribute lists and values of key-value pairs.
     (active, attr_literals, "1.13.0", Some(34981)),
 
-    // Allows the sysV64 ABI to be specified on all platforms
-    // instead of just the platforms on which it is the C ABI
-    (active, abi_sysv64, "1.13.0", Some(36167)),
-
     // Allows untagged unions `union U { ... }`
     (active, untagged_unions, "1.13.0", Some(32836)),
 
@@ -520,6 +516,9 @@ declare_features! (
     (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
     // Allow Drop types in constants (RFC 1440)
     (accepted, drop_types_in_const, "1.22.0", Some(33156)),
+    // Allows the sysV64 ABI to be specified on all platforms
+    // instead of just the platforms on which it is the C ABI
+    (accepted, abi_sysv64, "1.24.0", Some(36167)),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -718,6 +717,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                       is just used for rustc unit tests \
                                       and will never be stable",
                                      cfg_fn!(rustc_attrs))),
+    ("rustc_regions", Normal, Gated(Stability::Unstable,
+                                    "rustc_attrs",
+                                    "the `#[rustc_regions]` attribute \
+                                     is just used for rustc unit tests \
+                                     and will never be stable",
+                                    cfg_fn!(rustc_attrs))),
     ("rustc_error", Whitelisted, Gated(Stability::Unstable,
                                        "rustc_attrs",
                                        "the `#[rustc_error]` attribute \
@@ -1246,10 +1251,6 @@ impl<'a> PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, unboxed_closures, span,
                                    "rust-call ABI is subject to change");
             },
-            Abi::SysV64 => {
-                gate_feature_post!(&self, abi_sysv64, span,
-                                   "sysv64 ABI is experimental and subject to change");
-            },
             Abi::PtxKernel => {
                 gate_feature_post!(&self, abi_ptx, span,
                                    "PTX ABIs are experimental and subject to change");
@@ -1272,6 +1273,7 @@ impl<'a> PostExpansionVisitor<'a> {
             Abi::Fastcall |
             Abi::Aapcs |
             Abi::Win64 |
+            Abi::SysV64 |
             Abi::Rust |
             Abi::C |
             Abi::System => {}
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 6f20104dda5..d9c33fa50bd 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -14,7 +14,7 @@ use codemap::{CodeMap, FilePathMapping};
 use errors::{FatalError, DiagnosticBuilder};
 use parse::{token, ParseSess};
 use str::char_at;
-use symbol::{Symbol, keywords};
+use symbol::Symbol;
 use std_unicode::property::Pattern_White_Space;
 
 use std::borrow::Cow;
@@ -1296,18 +1296,6 @@ impl<'a> StringReader<'a> {
                         self.mk_ident(&format!("'{}", lifetime_name))
                     });
 
-                    // Conjure up a "keyword checking ident" to make sure that
-                    // the lifetime name is not a keyword.
-                    let keyword_checking_ident = self.with_str_from(start, |lifetime_name| {
-                        self.mk_ident(lifetime_name)
-                    });
-                    let keyword_checking_token = &token::Ident(keyword_checking_ident);
-                    let last_bpos = self.pos;
-                    if keyword_checking_token.is_reserved_ident() &&
-                       !keyword_checking_token.is_keyword(keywords::Static) {
-                        self.err_span_(start, last_bpos, "lifetimes cannot use keyword names");
-                    }
-
                     return Ok(token::Lifetime(ident));
                 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2461e65585f..726db733482 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5995,7 +5995,7 @@ impl<'a> Parser<'a> {
         match any_disr {
             Some(disr_span) if !all_nullary =>
                 self.span_err(disr_span,
-                    "discriminator values can only be used with a c-like enum"),
+                    "discriminator values can only be used with a field-less enum"),
             _ => ()
         }
 
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index bf059cac891..ec652b5607e 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -503,6 +503,8 @@ pub enum NonNarrowChar {
     ZeroWidth(BytePos),
     /// Represents a wide (fullwidth) character
     Wide(BytePos),
+    /// Represents a tab character, represented visually with a width of 4 characters
+    Tab(BytePos),
 }
 
 impl NonNarrowChar {
@@ -510,6 +512,7 @@ impl NonNarrowChar {
         match width {
             0 => NonNarrowChar::ZeroWidth(pos),
             2 => NonNarrowChar::Wide(pos),
+            4 => NonNarrowChar::Tab(pos),
             _ => panic!("width {} given for non-narrow character", width),
         }
     }
@@ -518,7 +521,8 @@ impl NonNarrowChar {
     pub fn pos(&self) -> BytePos {
         match *self {
             NonNarrowChar::ZeroWidth(p) |
-            NonNarrowChar::Wide(p) => p,
+            NonNarrowChar::Wide(p) |
+            NonNarrowChar::Tab(p) => p,
         }
     }
 
@@ -527,6 +531,7 @@ impl NonNarrowChar {
         match *self {
             NonNarrowChar::ZeroWidth(_) => 0,
             NonNarrowChar::Wide(_) => 2,
+            NonNarrowChar::Tab(_) => 4,
         }
     }
 }
@@ -538,6 +543,7 @@ impl Add<BytePos> for NonNarrowChar {
         match self {
             NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
             NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
+            NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs),
         }
     }
 }
@@ -549,6 +555,7 @@ impl Sub<BytePos> for NonNarrowChar {
         match self {
             NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
             NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
+            NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs),
         }
     }
 }
@@ -868,8 +875,10 @@ impl FileMap {
 
     pub fn record_width(&self, pos: BytePos, ch: char) {
         let width = match ch {
-            '\t' | '\n' =>
-                // Tabs will consume one column.
+            '\t' =>
+                // Tabs will consume 4 columns.
+                4,
+            '\n' =>
                 // Make newlines take one column so that displayed spans can point them.
                 1,
             ch =>
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 69ddd560213..aafdd696b74 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -35,6 +35,10 @@ impl Ident {
         Ident::with_empty_ctxt(Symbol::intern(string))
     }
 
+    pub fn without_first_quote(&self) -> Ident {
+        Ident { name: Symbol::from(self.name.as_str().trim_left_matches('\'')), ctxt: self.ctxt }
+    }
+
     pub fn modern(self) -> Ident {
         Ident { name: self.name, ctxt: self.ctxt.modern() }
     }
@@ -123,7 +127,12 @@ impl<'a> From<&'a str> for Symbol {
 
 impl fmt::Debug for Symbol {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}({})", self, self.0)
+        let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
+        if is_gensymed {
+            write!(f, "{}({})", self, self.0)
+        } else {
+            write!(f, "{}", self)
+        }
     }
 }
 
@@ -201,6 +210,10 @@ impl Interner {
         Symbol(!0 - self.gensyms.len() as u32 + 1)
     }
 
+    fn is_gensymed(&mut self, symbol: Symbol) -> bool {
+        symbol.0 as usize >= self.strings.len()
+    }
+
     pub fn get(&self, symbol: Symbol) -> &str {
         match self.strings.get(symbol.0 as usize) {
             Some(ref string) => string,
@@ -428,4 +441,10 @@ mod tests {
         // gensym of *existing* string gets new number:
         assert_eq!(i.gensym("dog"), Symbol(4294967293));
     }
+
+    #[test]
+    fn without_first_quote_test() {
+        let i = Ident::from_str("'break");
+        assert_eq!(i.without_first_quote().name, keywords::Break.name());
+    }
 }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 1797e19c549..072a9144f17 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -970,7 +970,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   std::set<GlobalValue::GUID> ExportedGUIDs;
   for (auto &List : Ret->Index) {
     for (auto &GVS: List.second) {
-      if (!GlobalValue::isExternalLinkage(GVS->linkage()))
+      if (GlobalValue::isLocalLinkage(GVS->linkage()))
         continue;
       auto GUID = GVS->getOriginalName();
       if (!DeadSymbols.count(GUID))
diff --git a/src/test/codegen/abi-sysv64.rs b/src/test/codegen/abi-sysv64.rs
index 4f6a50eab49..920f5cbcca3 100644
--- a/src/test/codegen/abi-sysv64.rs
+++ b/src/test/codegen/abi-sysv64.rs
@@ -18,7 +18,6 @@
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
-#![feature(abi_sysv64)]
 
 // CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
 #[no_mangle]
diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs
index 3f5725029d8..fa80a2efdf8 100644
--- a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs
+++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs
@@ -13,7 +13,7 @@
 
 fn cplusplus_mode(x: isize) -> &'static isize {
     &x //[ast]~ ERROR `x` does not live long enough
-       //[mir]~^ ERROR borrowed value does not live long enough
 }
+//[mir]~^ ERROR borrowed value does not live long enough
 
 fn main() {}
diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs
index 7009c6f33e6..78f0d321e0d 100644
--- a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs
+++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs
@@ -14,9 +14,9 @@
 fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) {
     let mut z = (0, 0);
     *x = Some(&mut z.1); //[ast]~ ERROR [E0597]
-                         //[mir]~^ ERROR [E0597]
     panic!("catch me for a dangling pointer!")
 }
+//[mir]~^ ERROR [E0597]
 
 fn main() {
     cplusplus_mode_exceptionally_unsafe(&mut None);
diff --git a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs
index c46bcbb32b9..2bd6f75df1b 100644
--- a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 #![feature(box_syntax)]
 
 fn call_f<F:FnOnce() -> isize>(f: F) -> isize {
@@ -18,5 +21,6 @@ fn main() {
     let t: Box<_> = box 3;
 
     call_f(move|| { *t + 1 });
-    call_f(move|| { *t + 1 }); //~ ERROR capture of moved value
+    call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value
+    //[mir]~^ ERROR use of moved value
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
index 6896d166e7a..63bb04a0e4c 100644
--- a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
@@ -23,15 +23,9 @@ fn main() {
             1 => { addr = &mut x; } //[ast]~ ERROR [E0499]
             //[mir]~^ ERROR [E0499]
             2 => { addr = &mut x; } //[ast]~ ERROR [E0499]
-            //[mir]~^ ERROR [E0506]
-            //[mir]~| ERROR [E0499]
-            //[mir]~| ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
             _ => { addr = &mut x; } //[ast]~ ERROR [E0499]
-            //[mir]~^ ERROR [E0506]
-            //[mir]~| ERROR [E0499]
-            //[mir]~| ERROR [E0499]
+            //[mir]~^ ERROR [E0499]
         }
     }
 }
-
-
diff --git a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
index f2e6d51d064..df0a05dfaee 100644
--- a/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
+++ b/src/test/compile-fail/borrowck/borrowck-thread-local-static-borrow-outlives-fn.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-test will be fixed later
 // revisions: ast mir
 //[mir]compile-flags: -Z borrowck=mir
 
diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
index 975de8b6c41..0241b3870c7 100644
--- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
+++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
@@ -52,12 +52,12 @@ fn main() {
         {
             let ra = &u.a;
             let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
-                                // FIXME Error for MIR (needs support for union)
+                                //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
         }
         {
             let ra = &u.a;
             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
-                     // FIXME Error for MIR (needs support for union)
+                     //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
         }
         // Mut borrow, same field
         {
@@ -84,22 +84,23 @@ fn main() {
         {
             let rma = &mut u.a;
             let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
-                           // FIXME Error for MIR (needs support for union)
+                           //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
         }
         {
             let ra = &mut u.a;
             let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
-                         // FIXME Error for MIR (needs support for union)
+                         //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
+
         }
         {
             let rma = &mut u.a;
             let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
-                                 // FIXME Error for MIR (needs support for union)
+                                 //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
         }
         {
             let rma = &mut u.a;
             u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
-                     // FIXME Error for MIR (needs support for union)
+                     //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
         }
     }
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
index 304a41c14ed..94877b27d58 100644
--- a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
@@ -1,3 +1,4 @@
+
 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
@@ -22,7 +23,7 @@ fn main() {
     println!("t[0]: {}", t[0]);
     a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
               //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast)
-              // FIXME Error for MIR (error missed)
+              //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir)
     println!("t[0]: {}", t[0]);
     t[0];
 }
diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/compile-fail/issue-10412.rs
index d723d94c02c..ee553730a35 100644
--- a/src/test/parse-fail/issue-10412.rs
+++ b/src/test/compile-fail/issue-10412.rs
@@ -8,16 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only -Z continue-parse-after-error
-
-
 trait Serializable<'self, T> { //~ ERROR lifetimes cannot use keyword names
-    fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR lifetimes cannot use keyword names
+    fn serialize(val : &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names
     fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR lifetimes cannot use keyword names
 }
 
 impl<'self> Serializable<str> for &'self str { //~ ERROR lifetimes cannot use keyword names
     //~^ ERROR lifetimes cannot use keyword names
+    //~| ERROR missing lifetime specifier
     fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR lifetimes cannot use keyword names
         vec![1]
     }
diff --git a/src/test/compile-fail/issue-25579.rs b/src/test/compile-fail/issue-25579.rs
index 9e12d5b5de1..5f5a58ed759 100644
--- a/src/test/compile-fail/issue-25579.rs
+++ b/src/test/compile-fail/issue-25579.rs
@@ -20,13 +20,9 @@ fn causes_ice(mut l: &mut Sexpression) {
     loop { match l {
         &mut Sexpression::Num(ref mut n) => {},
         &mut Sexpression::Cons(ref mut expr) => { //[ast]~ ERROR [E0499]
-                                                  //[mir]~^ ERROR [E0506]
-                                                  //[mir]~| ERROR [E0499]
+                                                  //[mir]~^ ERROR [E0499]
             l = &mut **expr; //[ast]~ ERROR [E0506]
                              //[mir]~^ ERROR [E0506]
-                             //[mir]~| ERROR [E0506]
-                             //[mir]~| ERROR [E0499]
-                             //[mir]~| ERROR [E0499]
         }
     }}
 }
diff --git a/src/test/compile-fail/no-core-gated.rs b/src/test/compile-fail/issue-46311.rs
index 27f8fda98ab..82f55f2c142 100644
--- a/src/test/compile-fail/no-core-gated.rs
+++ b/src/test/compile-fail/issue-46311.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-no_core
-
-#![no_core] //~ ERROR no_core is experimental
-
-fn main() {}
+fn main() {
+    'break: loop { //~ ERROR invalid label name `'break`
+    }
+}
diff --git a/src/test/parse-fail/lifetime-no-keyword.rs b/src/test/compile-fail/lifetime-no-keyword.rs
index a8771ae93af..d583c4fc6c6 100644
--- a/src/test/parse-fail/lifetime-no-keyword.rs
+++ b/src/test/compile-fail/lifetime-no-keyword.rs
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only -Z continue-parse-after-error
-
 fn foo<'a>(a: &'a isize) { }
 fn bar(a: &'static isize) { }
-fn baz(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names
-fn zab(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names
-
+fn baz<'let>(a: &'let isize) { } //~ ERROR lifetimes cannot use keyword names
+//~^ ERROR lifetimes cannot use keyword names
+fn zab<'self>(a: &'self isize) { } //~ ERROR lifetimes cannot use keyword names
+//~^ ERROR lifetimes cannot use keyword names
 fn main() { }
diff --git a/src/test/compile-fail/region-borrow-params-issue-29793-big.rs b/src/test/compile-fail/region-borrow-params-issue-29793-big.rs
index 887f7836ee1..a4dc00bd2b1 100644
--- a/src/test/compile-fail/region-borrow-params-issue-29793-big.rs
+++ b/src/test/compile-fail/region-borrow-params-issue-29793-big.rs
@@ -16,6 +16,10 @@
 // behavior (because the improperly accepted closure was actually
 // able to be invoked).
 
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
 struct WrapA<F>(Option<F>);
 
 impl<F> WrapA<F> {
@@ -75,9 +79,11 @@ impl<F, T> WrapA<F>
 fn main() {
     let mut w = WrapA::new().set(|x: usize, y: usize| {
         WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
-            //~^ ERROR `x` does not live long enough
-            //~| ERROR `y` does not live long enough
+            //[ast]~^ ERROR `x` does not live long enough
+            //[ast]~| ERROR `y` does not live long enough
     });
+    //[mir]~^ ERROR borrowed value does not live long enough
+    //[mir]~| ERROR borrowed value does not live long enough
 
     w.handle(); // This works
     // w.handle_ref(); // This doesn't
diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs
index de695e72d07..9de8ca196f8 100644
--- a/src/test/compile-fail/regions-static-bound.rs
+++ b/src/test/compile-fail/regions-static-bound.rs
@@ -8,17 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ll nll
+//[nll] compile-flags: -Znll -Zborrowck=mir
+
 fn static_id<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'static { t }
 fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
     where 'a: 'b, 'b: 'static { t }
 fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
-    t //~ ERROR E0312
+    t //[ll]~ ERROR E0312
+        //[nll]~^ WARNING not reporting region error due to -Znll
+        //[nll]~| ERROR free region `'a` does not outlive free region `'static`
 }
 
 fn error(u: &(), v: &()) {
-    static_id(&u); //~ ERROR cannot infer an appropriate lifetime
-    static_id_indirect(&v); //~ ERROR cannot infer an appropriate lifetime
+    static_id(&u); //[ll]~ ERROR cannot infer an appropriate lifetime
+    //[nll]~^ WARNING not reporting region error due to -Znll
+    static_id_indirect(&v); //[ll]~ ERROR cannot infer an appropriate lifetime
+    //[nll]~^ WARNING not reporting region error due to -Znll
+
+    // FIXME(#45827) -- MIR type checker shortcomings mean we don't
+    // see these errors (yet) in nll mode.
 }
 
 fn main() {}
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index a62d84fedf3..da8a62a9765 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index 4abc77e0ab6..d8a87da5918 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -27,16 +27,14 @@
 
 // Change closure body ---------------------------------------------------------
 #[cfg(cfail1)]
-fn change_closure_body() {
+pub fn change_closure_body() {
     let _ = || 1u32;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_closure_body() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_closure_body() {
     let _ = || 3u32;
 }
 
@@ -44,17 +42,15 @@ fn change_closure_body() {
 
 // Add parameter ---------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_parameter() {
+pub fn add_parameter() {
     let x = 0u32;
     let _ = || x + 1;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_parameter() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_parameter() {
     let x = 0u32;
     let _ = |x: u32| x + 1;
 }
@@ -63,16 +59,14 @@ fn add_parameter() {
 
 // Change parameter pattern ----------------------------------------------------
 #[cfg(cfail1)]
-fn change_parameter_pattern() {
+pub fn change_parameter_pattern() {
     let _ = |x: &u32| x;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_parameter_pattern() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_parameter_pattern() {
     let _ = |&x: &u32| x;
 }
 
@@ -80,16 +74,14 @@ fn change_parameter_pattern() {
 
 // Add `move` to closure -------------------------------------------------------
 #[cfg(cfail1)]
-fn add_move() {
+pub fn add_move() {
     let _ = || 1;
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_move() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_move() {
     let _ = move || 1;
 }
 
@@ -97,17 +89,15 @@ fn add_move() {
 
 // Add type ascription to parameter --------------------------------------------
 #[cfg(cfail1)]
-fn add_type_ascription_to_parameter() {
+pub fn add_type_ascription_to_parameter() {
     let closure = |x| x + 1u32;
     let _: u32 = closure(1);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_type_ascription_to_parameter() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
     let _: u32 = closure(1);
 }
@@ -116,17 +106,15 @@ fn add_type_ascription_to_parameter() {
 
 // Change parameter type -------------------------------------------------------
 #[cfg(cfail1)]
-fn change_parameter_type() {
+pub fn change_parameter_type() {
     let closure = |x: u32| (x as u64) + 1;
     let _ = closure(1);
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_parameter_type() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
     let _ = closure(1);
 }
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
index 496ae4276f8..47f5a2d2bbe 100644
--- a/src/test/incremental/hashes/consts.rs
+++ b/src/test/incremental/hashes/consts.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index f38d1864630..541261f1d80 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index dbb7aca1924..02746785856 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -23,7 +23,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
index 985c064f6a0..a796c87f19b 100644
--- a/src/test/incremental/hashes/exported_vs_not.rs
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -10,7 +10,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index 7ccb452b7ed..bcdd5661e71 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index 763b0cd05d4..105afd30d28 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -27,7 +27,7 @@
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_body() {
+pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
@@ -36,11 +36,9 @@ fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_body() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 2;
@@ -52,7 +50,7 @@ fn change_loop_body() {
 
 // Change iteration variable name ----------------------------------------------
 #[cfg(cfail1)]
-fn change_iteration_variable_name() {
+pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _i in 0..1 {
         _x = 1;
@@ -61,11 +59,9 @@ fn change_iteration_variable_name() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_iteration_variable_name() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _a in 0..1 {
         _x = 1;
@@ -77,7 +73,7 @@ fn change_iteration_variable_name() {
 
 // Change iteration variable pattern -------------------------------------------
 #[cfg(cfail1)]
-fn change_iteration_variable_pattern() {
+pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
     for _i in &[0, 1, 2] {
         _x = 1;
@@ -86,11 +82,9 @@ fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_iteration_variable_pattern() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
     for &_i in &[0, 1, 2] {
         _x = 1;
@@ -102,7 +96,7 @@ fn change_iteration_variable_pattern() {
 
 // Change iterable -------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_iterable() {
+pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 2] {
         _x = 1;
@@ -111,11 +105,9 @@ fn change_iterable() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_iterable() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 3] {
         _x = 1;
@@ -127,7 +119,7 @@ fn change_iterable() {
 
 // Add break -------------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_break() {
+pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
@@ -135,11 +127,9 @@ fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
@@ -151,7 +141,7 @@ fn add_break() {
 
 // Add loop label --------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label() {
+pub fn add_loop_label() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
@@ -160,11 +150,9 @@ fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
@@ -176,7 +164,7 @@ fn add_loop_label() {
 
 // Add loop label to break -----------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_break() {
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
@@ -185,11 +173,9 @@ fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
@@ -201,7 +187,7 @@ fn add_loop_label_to_break() {
 
 // Change break label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_break_label() {
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
         'inner: for _ in 0..1 {
@@ -212,11 +198,9 @@ fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_break_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
         'inner: for _ in 0..1 {
@@ -230,7 +214,7 @@ fn change_break_label() {
 
 // Add loop label to continue --------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_continue() {
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
@@ -239,11 +223,9 @@ fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_continue() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
@@ -255,7 +237,7 @@ fn add_loop_label_to_continue() {
 
 // Change continue label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_label() {
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
         'inner: for _ in 0..1 {
@@ -266,11 +248,9 @@ fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
         'inner: for _ in 0..1 {
@@ -284,7 +264,7 @@ fn change_continue_label() {
 
 // Change continue to break ----------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_to_break() {
+pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
@@ -293,11 +273,9 @@ fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index b3eb566367c..abe0586efcd 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
@@ -26,245 +26,253 @@
 #![feature(intrinsics)]
 #![feature(linkage)]
 #![feature(rustc_attrs)]
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 
 
 // Add Parameter ---------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn add_parameter() {}
+pub fn add_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn add_parameter(p: i32) {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn add_parameter(p: i32) {}
 
 
 // Add Return Type -------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn add_return_type() {}
+pub fn add_return_type() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn add_return_type() -> () {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn add_return_type() -> () {}
 
 
 // Change Parameter Type -------------------------------------------------------
 
 #[cfg(cfail1)]
-fn type_of_parameter(p: i32) {}
+pub fn type_of_parameter(p: i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn type_of_parameter(p: i64) {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn type_of_parameter(p: i64) {}
 
 
 // Change Parameter Type Reference ---------------------------------------------
 
 #[cfg(cfail1)]
-fn type_of_parameter_ref(p: &i32) {}
+pub fn type_of_parameter_ref(p: &i32) {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn type_of_parameter_ref(p: &mut i32) {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn type_of_parameter_ref(p: &mut i32) {}
 
 
 // Change Parameter Order ------------------------------------------------------
 
 #[cfg(cfail1)]
-fn order_of_parameters(p1: i32, p2: i64) {}
+pub fn order_of_parameters(p1: i32, p2: i64) {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn order_of_parameters(p2: i64, p1: i32) {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn order_of_parameters(p2: i64, p1: i32) {}
 
 
 // Unsafe ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn make_unsafe() {}
+pub fn make_unsafe() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-unsafe fn make_unsafe() {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub unsafe fn make_unsafe() {}
 
 
 // Extern ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn make_extern() {}
+pub fn make_extern() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-extern fn make_extern() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub extern "C" fn make_extern() {}
 
 
 // Extern C Extern Rust-Intrinsic ----------------------------------------------
 
 #[cfg(cfail1)]
-extern "C" fn make_intrinsic() {}
+pub extern "C" fn make_intrinsic() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-extern "rust-intrinsic" fn make_intrinsic() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub extern "rust-intrinsic" fn make_intrinsic() {}
 
 
 // Type Parameter --------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn type_parameter() {}
+pub fn type_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn type_parameter<T>() {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn type_parameter<T>() {}
 
 
 // Lifetime Parameter ----------------------------------------------------------
 
 #[cfg(cfail1)]
-fn lifetime_parameter() {}
+pub fn lifetime_parameter() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn lifetime_parameter<'a>() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, GenericsOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn lifetime_parameter<'a>() {}
 
 
 // Trait Bound -----------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn trait_bound<T>() {}
+pub fn trait_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn trait_bound<T: Eq>() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn trait_bound<T: Eq>() {}
 
 
 // Builtin Bound ---------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn builtin_bound<T>() {}
+pub fn builtin_bound<T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn builtin_bound<T: Send>() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn builtin_bound<T: Send>() {}
 
 
 // Lifetime Bound --------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn lifetime_bound<'a, T>() {}
+pub fn lifetime_bound<'a, T>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn lifetime_bound<'a, T: 'a>() {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn lifetime_bound<'a, T: 'a>() {}
 
 
 // Second Trait Bound ----------------------------------------------------------
 
 #[cfg(cfail1)]
-fn second_trait_bound<T: Eq>() {}
+pub fn second_trait_bound<T: Eq>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn second_trait_bound<T: Eq + Clone>() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn second_trait_bound<T: Eq + Clone>() {}
 
 
 // Second Builtin Bound --------------------------------------------------------
 
 #[cfg(cfail1)]
-fn second_builtin_bound<T: Send>() {}
+pub fn second_builtin_bound<T: Send>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn second_builtin_bound<T: Send + Sized>() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn second_builtin_bound<T: Send + Sized>() {}
 
 
 // Second Lifetime Bound -------------------------------------------------------
 
 #[cfg(cfail1)]
-fn second_lifetime_bound<'a, 'b, T: 'a>() {}
+pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
+#[rustc_clean(cfg = "cfail2",
+              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
 
 // Inline ----------------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn inline() {}
+pub fn inline() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
 #[inline]
-fn inline() {}
+pub fn inline() {}
 
 
 // Inline Never ----------------------------------------------------------------
 
 #[cfg(cfail1)]
 #[inline(always)]
-fn inline_never() {}
+pub fn inline_never() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
 #[inline(never)]
-fn inline_never() {}
+pub fn inline_never() {}
 
 
 // No Mangle -------------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn no_mangle() {}
+pub fn no_mangle() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
 #[no_mangle]
-fn no_mangle() {}
+pub fn no_mangle() {}
 
 
 // Linkage ---------------------------------------------------------------------
 
 #[cfg(cfail1)]
-fn linkage() {}
+pub fn linkage() {}
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[linkage="weak_odr"]
-fn linkage() {}
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
+#[linkage = "weak_odr"]
+pub fn linkage() {}
 
 
 // Return Impl Trait -----------------------------------------------------------
 
 #[cfg(cfail1)]
-fn return_impl_trait() -> i32 {
+pub fn return_impl_trait() -> i32 {
     0
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn return_impl_trait() -> impl Clone {
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn return_impl_trait() -> impl Clone {
     0
 }
 
@@ -272,32 +280,33 @@ fn return_impl_trait() -> impl Clone {
 // Change Return Impl Trait ----------------------------------------------------
 
 #[cfg(cfail1)]
-fn change_return_impl_trait() -> impl Clone {
+pub fn change_return_impl_trait() -> impl Clone {
     0u32
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-fn change_return_impl_trait() -> impl Copy {
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
+#[rustc_clean(cfg = "cfail3")]
+pub fn change_return_impl_trait() -> impl Copy {
     0u32
 }
 
 
 // Change Return Type Indirectly -----------------------------------------------
 
-struct ReferencedType1;
-struct ReferencedType2;
+pub struct ReferencedType1;
+pub struct ReferencedType2;
 
-mod change_return_type_indirectly {
+pub mod change_return_type_indirectly {
     #[cfg(cfail1)]
     use super::ReferencedType1 as ReturnType;
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ReturnType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    fn indirect_return_type() -> ReturnType {
+    #[rustc_clean(cfg = "cfail2",
+                  except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+    #[rustc_clean(cfg = "cfail3")]
+    pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
     }
 }
@@ -305,44 +314,49 @@ mod change_return_type_indirectly {
 
 // Change Parameter Type Indirectly --------------------------------------------
 
-mod change_parameter_type_indirectly {
+pub mod change_parameter_type_indirectly {
     #[cfg(cfail1)]
     use super::ReferencedType1 as ParameterType;
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as ParameterType;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    fn indirect_parameter_type(p: ParameterType) {}
+    #[rustc_clean(cfg = "cfail2",
+                  except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
+    #[rustc_clean(cfg = "cfail3")]
+    pub fn indirect_parameter_type(p: ParameterType) {}
 }
 
 
 // Change Trait Bound Indirectly -----------------------------------------------
 
-trait ReferencedTrait1 {}
-trait ReferencedTrait2 {}
+pub trait ReferencedTrait1 {}
+pub trait ReferencedTrait2 {}
 
-mod change_trait_bound_indirectly {
+pub mod change_trait_bound_indirectly {
     #[cfg(cfail1)]
     use super::ReferencedTrait1 as Trait;
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    fn indirect_trait_bound<T: Trait>(p: T) {}
+    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+    #[rustc_clean(cfg = "cfail3")]
+    pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
 
 
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 
-mod change_trait_bound_indirectly_in_where_clause {
+pub mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(cfail1)]
     use super::ReferencedTrait1 as Trait;
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="Hir", cfg="cfail3")]
-    fn indirect_trait_bound_where<T>(p: T) where T: Trait {}
+    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
+    #[rustc_clean(cfg = "cfail3")]
+    pub fn indirect_trait_bound_where<T>(p: T)
+    where
+        T: Trait,
+    {
+    }
 }
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index d6878028cfa..426c58c834d 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index 715146146f1..e66e239b33c 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index c8c2fa5e8c8..93aba4a3ee1 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index 0947239c573..b93a9656603 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -30,7 +30,7 @@
 // Change template -------------------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_template(a: i32) -> i32 {
+pub fn change_template(a: i32) -> i32 {
     let c: i32;
     unsafe {
         asm!("add 1, $0"
@@ -44,12 +44,10 @@ fn change_template(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_template(a: i32) -> i32 {
+pub fn change_template(a: i32) -> i32 {
     let c: i32;
     unsafe {
         asm!("add 2, $0"
@@ -67,7 +65,7 @@ fn change_template(a: i32) -> i32 {
 // Change output -------------------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_output(a: i32) -> i32 {
+pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
     let mut _out2: i32 = 0;
     unsafe {
@@ -82,12 +80,10 @@ fn change_output(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_output(a: i32) -> i32 {
+pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
     let mut _out2: i32 = 0;
     unsafe {
@@ -106,7 +102,7 @@ fn change_output(a: i32) -> i32 {
 // Change input -------------------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_input(_a: i32, _b: i32) -> i32 {
+pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -120,12 +116,10 @@ fn change_input(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_input(_a: i32, _b: i32) -> i32 {
+pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -143,7 +137,7 @@ fn change_input(_a: i32, _b: i32) -> i32 {
 // Change input constraint -----------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -157,12 +151,10 @@ fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_input_constraint(_a: i32, _b: i32) -> i32 {
+pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -180,7 +172,7 @@ fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 // Change clobber --------------------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_clobber(_a: i32) -> i32 {
+pub fn change_clobber(_a: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -194,12 +186,10 @@ fn change_clobber(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_clobber(_a: i32) -> i32 {
+pub fn change_clobber(_a: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -217,7 +207,7 @@ fn change_clobber(_a: i32) -> i32 {
 // Change options --------------------------------------------------------------
 #[cfg(cfail1)]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_options(_a: i32) -> i32 {
+pub fn change_options(_a: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
@@ -231,12 +221,10 @@ fn change_options(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn change_options(_a: i32) -> i32 {
+pub fn change_options(_a: i32) -> i32 {
     let _out;
     unsafe {
         asm!("add 1, $0"
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index f3bddc66984..851b13c7055 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index 8d015288757..dcb937fd867 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -27,7 +27,7 @@
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_body() {
+pub fn change_loop_body() {
     let mut _x = 0;
     loop {
         _x = 1;
@@ -36,11 +36,9 @@ fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_body() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_body() {
     let mut _x = 0;
     loop {
         _x = 2;
@@ -52,7 +50,7 @@ fn change_loop_body() {
 
 // Add break -------------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_break() {
+pub fn add_break() {
     let mut _x = 0;
     loop {
         _x = 1;
@@ -60,11 +58,9 @@ fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_break() {
     let mut _x = 0;
     loop {
         _x = 1;
@@ -76,7 +72,7 @@ fn add_break() {
 
 // Add loop label --------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label() {
+pub fn add_loop_label() {
     let mut _x = 0;
     loop {
         _x = 1;
@@ -85,11 +81,9 @@ fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
@@ -101,7 +95,7 @@ fn add_loop_label() {
 
 // Add loop label to break -----------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_break() {
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
@@ -110,11 +104,9 @@ fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
@@ -126,7 +118,7 @@ fn add_loop_label_to_break() {
 
 // Change break label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_break_label() {
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
         'inner: loop {
@@ -137,11 +129,9 @@ fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_break_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
         'inner: loop {
@@ -155,7 +145,7 @@ fn change_break_label() {
 
 // Add loop label to continue --------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_continue() {
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
@@ -164,11 +154,9 @@ fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_continue() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
@@ -180,7 +168,7 @@ fn add_loop_label_to_continue() {
 
 // Change continue label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_label() {
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
         'inner: loop {
@@ -191,11 +179,9 @@ fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
         'inner: loop {
@@ -209,7 +195,7 @@ fn change_continue_label() {
 
 // Change continue to break ----------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_to_break() {
+pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
         _x = 1;
@@ -218,11 +204,9 @@ fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
         _x = 1;
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
index 38edd675cc6..263901f4025 100644
--- a/src/test/incremental/hashes/match_expressions.rs
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
index c76c10f2ab4..2b6a140be32 100644
--- a/src/test/incremental/hashes/panic_exprs.rs
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -28,155 +28,134 @@
 
 
 // Indexing expression ---------------------------------------------------------
-#[cfg(cfail1)]
-pub fn indexing(slice: &[u8]) -> u8 {
-    slice[100]
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn indexing(slice: &[u8]) -> u8 {
-    slice[100]
+    #[cfg(cfail1)]
+    {
+        slice[100]
+    }
+    #[cfg(not(cfail1))]
+    {
+        slice[100]
+    }
 }
 
 
 // Arithmetic overflow plus ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_plus(val: i32) -> i32 {
-    val + 1
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_plus(val: i32) -> i32 {
-    val + 1
+    #[cfg(cfail1)]
+    {
+        val + 1
+    }
+    #[cfg(not(cfail1))]
+    {
+        val + 1
+    }
 }
 
 
 // Arithmetic overflow minus ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_minus(val: i32) -> i32 {
-    val - 1
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_minus(val: i32) -> i32 {
-    val - 1
+    #[cfg(cfail1)]
+    {
+        val - 1
+    }
+    #[cfg(not(cfail1))]
+    {
+        val - 1
+    }
 }
 
 
 // Arithmetic overflow mult ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_mult(val: i32) -> i32 {
-    val * 2
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_mult(val: i32) -> i32 {
-    val * 2
+    #[cfg(cfail1)]
+    {
+        val * 2
+    }
+    #[cfg(not(cfail1))]
+    {
+        val * 2
+    }
 }
 
 
 // Arithmetic overflow negation ------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_negation(val: i32) -> i32 {
-    -val
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_negation(val: i32) -> i32 {
-    -val
+    #[cfg(cfail1)]
+    {
+        -val
+    }
+    #[cfg(not(cfail1))]
+    {
+        -val
+    }
 }
 
 
 // Division by zero ------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn division_by_zero(val: i32) -> i32 {
-    2 / val
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn division_by_zero(val: i32) -> i32 {
-    2 / val
+    #[cfg(cfail1)]
+    {
+        2 / val
+    }
+    #[cfg(not(cfail1))]
+    {
+        2 / val
+    }
 }
 
 // Division by zero ------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn mod_by_zero(val: i32) -> i32 {
-    2 % val
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn mod_by_zero(val: i32) -> i32 {
-    2 % val
+    #[cfg(cfail1)]
+    {
+        2 % val
+    }
+    #[cfg(not(cfail1))]
+    {
+        2 % val
+    }
 }
 
 
 // shift left ------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn shift_left(val: i32, shift: usize) -> i32 {
-    val << shift
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_left(val: i32, shift: usize) -> i32 {
-    val << shift
+    #[cfg(cfail1)]
+    {
+        val << shift
+    }
+    #[cfg(not(cfail1))]
+    {
+        val << shift
+    }
 }
 
 
 // shift right ------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn shift_right(val: i32, shift: usize) -> i32 {
-    val >> shift
-}
-
-#[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_right(val: i32, shift: usize) -> i32 {
-    val >> shift
-}
-
-
-// THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION
-
-// bitwise ---------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382
-}
-
-
-// logical ---------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn logical(val1: bool, val2: bool, val3: bool) -> bool {
-    val1 && val2 || val3
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn logical(val1: bool, val2: bool, val3: bool) -> bool {
-    val1 && val2 || val3
+    #[cfg(cfail1)]
+    {
+        val >> shift
+    }
+    #[cfg(not(cfail1))]
+    {
+        val >> shift
+    }
 }
diff --git a/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs b/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs
deleted file mode 100644
index 8402da04091..00000000000
--- a/src/test/incremental/hashes/panic_exprs_no_overflow_checks.rs
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This test case tests the incremental compilation hash (ICH) implementation
-// for exprs that can panic at runtime (e.g. because of bounds checking). For
-// these expressions an error message containing their source location is
-// generated, so their hash must always depend on their location in the source
-// code, not just when debuginfo is enabled.
-
-// As opposed to the panic_exprs.rs test case, this test case checks that things
-// behave as expected when overflow checks are off:
-//
-// - Addition, subtraction, and multiplication do not change the ICH, unless
-//   the function containing them is marked with rustc_inherit_overflow_checks.
-// - Division by zero and bounds checks always influence the ICH
-
-// The general pattern followed here is: Change one thing between rev1 and rev2
-// and make sure that the hash has changed, then change nothing between rev2 and
-// rev3 and make sure that the hash has not changed.
-
-// must-compile-successfully
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Z force-overflow-checks=off
-
-#![allow(warnings)]
-#![feature(rustc_attrs)]
-#![crate_type="rlib"]
-
-
-// Indexing expression ---------------------------------------------------------
-#[cfg(cfail1)]
-pub fn indexing(slice: &[u8]) -> u8 {
-    slice[100]
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-pub fn indexing(slice: &[u8]) -> u8 {
-    slice[100]
-}
-
-
-// Arithmetic overflow plus ----------------------------------------------------
-#[cfg(cfail1)]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_plus_inherit(val: i32) -> i32 {
-    val + 1
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_plus_inherit(val: i32) -> i32 {
-    val + 1
-}
-
-
-// Arithmetic overflow minus ----------------------------------------------------
-#[cfg(cfail1)]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_minus_inherit(val: i32) -> i32 {
-    val - 1
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_minus_inherit(val: i32) -> i32 {
-    val - 1
-}
-
-
-// Arithmetic overflow mult ----------------------------------------------------
-#[cfg(cfail1)]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_mult_inherit(val: i32) -> i32 {
-    val * 2
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_mult_inherit(val: i32) -> i32 {
-    val * 2
-}
-
-
-// Arithmetic overflow negation ------------------------------------------------
-#[cfg(cfail1)]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_negation_inherit(val: i32) -> i32 {
-    -val
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-#[rustc_inherit_overflow_checks]
-pub fn arithmetic_overflow_negation_inherit(val: i32) -> i32 {
-    -val
-}
-
-
-// Division by zero ------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn division_by_zero(val: i32) -> i32 {
-    2 / val
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-pub fn division_by_zero(val: i32) -> i32 {
-    2 / val
-}
-
-// Division by zero ------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn mod_by_zero(val: i32) -> i32 {
-    2 % val
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
-#[rustc_clean(cfg="cfail3")]
-pub fn mod_by_zero(val: i32) -> i32 {
-    2 % val
-}
-
-
-
-// THE FOLLOWING ITEMS SHOULD NOT BE INFLUENCED BY THEIR SOURCE LOCATION
-
-// bitwise ---------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
-}
-
-
-// logical ---------------------------------------------------------------------
-#[cfg(cfail1)]
-pub fn logical(val1: bool, val2: bool, val3: bool) -> bool {
-    val1 && val2 || val3
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn logical(val1: bool, val2: bool, val3: bool) -> bool {
-    val1 && val2 || val3
-}
-
-// Arithmetic overflow plus ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_plus(val: i32) -> i32 {
-    val + 1
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn arithmetic_overflow_plus(val: i32) -> i32 {
-    val + 1
-}
-
-
-// Arithmetic overflow minus ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_minus(val: i32) -> i32 {
-    val - 1
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn arithmetic_overflow_minus(val: i32) -> i32 {
-    val - 1
-}
-
-
-// Arithmetic overflow mult ----------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_mult(val: i32) -> i32 {
-    val * 2
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn arithmetic_overflow_mult(val: i32) -> i32 {
-    val * 2
-}
-
-
-// Arithmetic overflow negation ------------------------------------------------
-#[cfg(cfail1)]
-pub fn arithmetic_overflow_negation(val: i32) -> i32 {
-    -val
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
-#[rustc_clean(cfg="cfail3")]
-pub fn arithmetic_overflow_negation(val: i32) -> i32 {
-    -val
-}
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
index e729a2c039e..b9616d8c6b5 100644
--- a/src/test/incremental/hashes/statics.rs
+++ b/src/test/incremental/hashes/statics.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index a16f4a2fdfd..3cdaf0e468a 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index d89d779c849..d7b70720418 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -23,7 +23,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index e09659be755..0816d6e5f45 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -23,7 +23,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
index eb31175b6f2..a232883f7a9 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 
 #![allow(warnings)]
diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs
index 59346f5fdb2..c5521d2fae2 100644
--- a/src/test/incremental/hashes/type_defs.rs
+++ b/src/test/incremental/hashes/type_defs.rs
@@ -23,7 +23,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index ec4ae62b12b..85f6ef60c5d 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Z force-overflow-checks=off
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index eae5aea6510..d04ed03eb66 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -27,7 +27,7 @@
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_body() {
+pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -36,11 +36,9 @@ fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_body() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 2;
@@ -52,7 +50,7 @@ fn change_loop_body() {
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_condition() {
+pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -61,11 +59,9 @@ fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_condition() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(1u32) = None {
         _x = 1;
@@ -77,7 +73,7 @@ fn change_loop_condition() {
 
 // Add break -------------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_break() {
+pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -85,11 +81,9 @@ fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -101,7 +95,7 @@ fn add_break() {
 
 // Add loop label --------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label() {
+pub fn add_loop_label() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -110,11 +104,9 @@ fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
@@ -126,7 +118,7 @@ fn add_loop_label() {
 
 // Add loop label to break -----------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_break() {
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
@@ -135,11 +127,9 @@ fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
@@ -151,7 +141,7 @@ fn add_loop_label_to_break() {
 
 // Change break label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_break_label() {
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
         'inner: while let Some(0u32) = None {
@@ -162,11 +152,9 @@ fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_break_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
         'inner: while let Some(0u32) = None {
@@ -180,7 +168,7 @@ fn change_break_label() {
 
 // Add loop label to continue --------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_continue() {
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
@@ -189,11 +177,9 @@ fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_continue() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
@@ -205,7 +191,7 @@ fn add_loop_label_to_continue() {
 
 // Change continue label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_label() {
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
         'inner: while let Some(0u32) = None {
@@ -216,11 +202,9 @@ fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
         'inner: while let Some(0u32) = None {
@@ -234,7 +218,7 @@ fn change_continue_label() {
 
 // Change continue to break ----------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_to_break() {
+pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
@@ -243,11 +227,9 @@ fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index 6b1898e401b..7f2bbebde80 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -18,7 +18,7 @@
 
 // must-compile-successfully
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -27,7 +27,7 @@
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_body() {
+pub fn change_loop_body() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -36,11 +36,9 @@ fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_body() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_body() {
     let mut _x = 0;
     while true {
         _x = 2;
@@ -52,7 +50,7 @@ fn change_loop_body() {
 
 // Change loop body ------------------------------------------------------------
 #[cfg(cfail1)]
-fn change_loop_condition() {
+pub fn change_loop_condition() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -61,11 +59,9 @@ fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_loop_condition() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_loop_condition() {
     let mut _x = 0;
     while false {
         _x = 1;
@@ -77,7 +73,7 @@ fn change_loop_condition() {
 
 // Add break -------------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_break() {
+pub fn add_break() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -85,11 +81,9 @@ fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_break() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -101,7 +95,7 @@ fn add_break() {
 
 // Add loop label --------------------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label() {
+pub fn add_loop_label() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -110,11 +104,9 @@ fn add_loop_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
@@ -126,7 +118,7 @@ fn add_loop_label() {
 
 // Add loop label to break -----------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_break() {
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
@@ -135,11 +127,9 @@ fn add_loop_label_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
@@ -151,7 +141,7 @@ fn add_loop_label_to_break() {
 
 // Change break label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_break_label() {
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
         'inner: while true {
@@ -162,11 +152,9 @@ fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_break_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
         'inner: while true {
@@ -180,7 +168,7 @@ fn change_break_label() {
 
 // Add loop label to continue --------------------------------------------------
 #[cfg(cfail1)]
-fn add_loop_label_to_continue() {
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
@@ -189,11 +177,9 @@ fn add_loop_label_to_continue() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn add_loop_label_to_continue() {
+#[rustc_clean(cfg="cfail2", except="HirBody")]
+#[rustc_clean(cfg="cfail3")]
+pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
@@ -205,7 +191,7 @@ fn add_loop_label_to_continue() {
 
 // Change continue label ----------------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_label() {
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
         'inner: while true {
@@ -216,11 +202,9 @@ fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_label() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
         'inner: while true {
@@ -234,7 +218,7 @@ fn change_continue_label() {
 
 // Change continue to break ----------------------------------------------------
 #[cfg(cfail1)]
-fn change_continue_to_break() {
+pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
         _x = 1;
@@ -243,11 +227,9 @@ fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="Hir", cfg="cfail2")]
-#[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_dirty(label="HirBody", cfg="cfail2")]
-#[rustc_clean(label="HirBody", cfg="cfail3")]
-fn change_continue_to_break() {
+#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, MirOptimized")]
+#[rustc_clean(cfg="cfail3")]
+pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
         _x = 1;
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
index 7f4e2b0f176..996c9ed21cf 100644
--- a/src/test/incremental/ich_method_call_trait_scope.rs
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -30,21 +30,10 @@ trait Trait2 {
 
 impl Trait2 for () { }
 
-#[cfg(rpass1)]
 mod mod3 {
+    #[cfg(rpass1)]
     use Trait1;
-
-    fn bar() {
-        ().method();
-    }
-
-    fn baz() {
-        22; // no method call, traits in scope don't matter
-    }
-}
-
-#[cfg(rpass2)]
-mod mod3 {
+    #[cfg(rpass2)]
     use Trait2;
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index 2e0f0ba0837..8566a24c84b 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -17,23 +17,18 @@
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[cfg(cfail1)]
-pub fn foo() {
-    pub fn bar() { }
-    pub fn baz() { }
-}
-
-#[cfg(cfail2)]
 #[rustc_clean(label="Hir", cfg="cfail2")]
 #[rustc_dirty(label="HirBody", cfg="cfail2")]
 pub fn foo() {
-    #[rustc_clean(label="Hir", cfg="cfail2")]
-    #[rustc_clean(label="HirBody", cfg="cfail2")]
+    #[cfg(cfail1)]
     pub fn baz() { } // order is different...
 
     #[rustc_clean(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="HirBody", cfg="cfail2")]
     pub fn bar() { } // but that doesn't matter.
 
+    #[cfg(cfail2)]
+    pub fn baz() { } // order is different...
+
     pub fn bap() { } // neither does adding a new item
 }
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
index 49a88c530ff..9e5b51f3e7a 100644
--- a/src/test/incremental/ich_resolve_results.rs
+++ b/src/test/incremental/ich_resolve_results.rs
@@ -25,49 +25,29 @@ mod mod2 {
     pub struct Foo(pub i64);
 }
 
-#[cfg(rpass1)]
 mod mod3 {
-    use test;
+    #[cfg(rpass1)]
     use mod1::Foo;
-
-    fn in_expr() {
-        Foo(0);
-    }
-
-    fn in_type() {
-        test::<Foo>();
-    }
-}
-
-#[cfg(rpass2)]
-mod mod3 {
-    use mod1::Foo; // <-- Nothing changed, but reordered!
     use test;
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn in_expr() {
-        Foo(0);
-    }
+    // In rpass2 we move the use declaration.
+    #[cfg(rpass2)]
+    use mod1::Foo;
+
+    // In rpass3 we let the declaration point to something else.
+    #[cfg(rpass3)]
+    use mod2::Foo;
 
     #[rustc_clean(label="Hir", cfg="rpass2")]
     #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn in_type() {
-        test::<Foo>();
-    }
-}
-
-#[cfg(rpass3)]
-mod mod3 {
-    use test;
-    use mod2::Foo; // <-- This changed!
-
     #[rustc_clean(label="Hir", cfg="rpass3")]
     #[rustc_dirty(label="HirBody", cfg="rpass3")]
     fn in_expr() {
         Foo(0);
     }
 
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    #[rustc_clean(label="HirBody", cfg="rpass2")]
     #[rustc_clean(label="Hir", cfg="rpass3")]
     #[rustc_dirty(label="HirBody", cfg="rpass3")]
     fn in_type() {
diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs
index 36d1b3ecbcd..3f669ae3fc8 100644
--- a/src/test/incremental/source_loc_macros.rs
+++ b/src/test/incremental/source_loc_macros.rs
@@ -35,28 +35,30 @@ fn file_same() {
     let _ = file!();
 }
 
-#[cfg(rpass1)]
-fn line_different() {
-    let _ = line!();
-}
-
-#[cfg(rpass2)]
 #[rustc_clean(label="Hir", cfg="rpass2")]
 #[rustc_dirty(label="HirBody", cfg="rpass2")]
 fn line_different() {
-    let _ = line!();
-}
-
-#[cfg(rpass1)]
-fn col_different() {
-    let _ = column!();
+    #[cfg(rpass1)]
+    {
+        let _ = line!();
+    }
+    #[cfg(rpass2)]
+    {
+        let _ = line!();
+    }
 }
 
-#[cfg(rpass2)]
 #[rustc_clean(label="Hir", cfg="rpass2")]
 #[rustc_dirty(label="HirBody", cfg="rpass2")]
 fn col_different() {
-    let _ =        column!();
+    #[cfg(rpass1)]
+    {
+        let _ = column!();
+    }
+    #[cfg(rpass2)]
+    {
+        let _ =        column!();
+    }
 }
 
 fn main() {
diff --git a/src/test/incremental/spans_insignificant_w_o_debuginfo.rs b/src/test/incremental/spans_insignificant_w_o_debuginfo.rs
deleted file mode 100644
index 90ec4a9d558..00000000000
--- a/src/test/incremental/spans_insignificant_w_o_debuginfo.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This test makes sure that just changing a definition's location in the
-// source file does *not* change its incr. comp. hash, if debuginfo is disabled.
-
-// revisions:rpass1 rpass2
-
-// compile-flags: -Z query-dep-graph
-
-#![feature(rustc_attrs)]
-
-#[cfg(rpass1)]
-pub fn main() {}
-
-#[cfg(rpass2)]
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
-pub fn main() {}
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index c0bf35e781c..1fefec7a0a7 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -23,8 +23,7 @@ pub fn main() {
 }
 
 #[cfg(rpass2)]
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_dirty(label="HirBody", cfg="rpass2")]
+#[rustc_dirty(label="MirOptimized", cfg="rpass2")]
 pub fn main() {
     let _ = 0u8 + 1;
 }
diff --git a/src/test/mir-opt/nll/liveness-call-subtlety.rs b/src/test/mir-opt/nll/liveness-call-subtlety.rs
index e4dd99f5a1e..09288cf69ff 100644
--- a/src/test/mir-opt/nll/liveness-call-subtlety.rs
+++ b/src/test/mir-opt/nll/liveness-call-subtlety.rs
@@ -28,18 +28,18 @@ fn main() {
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb0: []
 //    bb0: {
-//            | Live variables at bb0[0]: []
+//            | Live variables on entry to bb0[0]: []
 //        StorageLive(_1);
-//            | Live variables at bb0[1]: []
+//            | Live variables on entry to bb0[1]: []
 //        _1 = const <std::boxed::Box<T>>::new(const 22usize) -> [return: bb2, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb2: [_1 (drop)]
 //    bb2: {
-//            | Live variables at bb2[0]: [_1 (drop)]
+//            | Live variables on entry to bb2[0]: [_1 (drop)]
 //        StorageLive(_2);
-//            | Live variables at bb2[1]: [_1 (drop)]
+//            | Live variables on entry to bb2[1]: [_1 (drop)]
 //        _2 = const can_panic() -> [return: bb3, unwind: bb4];
 //    }
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/liveness-drop-intra-block.rs b/src/test/mir-opt/nll/liveness-drop-intra-block.rs
index 8dae7738067..b060222a95f 100644
--- a/src/test/mir-opt/nll/liveness-drop-intra-block.rs
+++ b/src/test/mir-opt/nll/liveness-drop-intra-block.rs
@@ -27,15 +27,15 @@ fn main() {
 // START rustc.main.nll.0.mir
 //    | Live variables on entry to bb2: []
 //    bb2: {
-//            | Live variables at bb2[0]: []
+//            | Live variables on entry to bb2[0]: []
 //        _1 = const 55usize;
-//            | Live variables at bb2[1]: [_1]
+//            | Live variables on entry to bb2[1]: [_1]
 //        StorageLive(_3);
-//            | Live variables at bb2[2]: [_1]
+//            | Live variables on entry to bb2[2]: [_1]
 //        StorageLive(_4);
-//            | Live variables at bb2[3]: [_1]
+//            | Live variables on entry to bb2[3]: [_1]
 //        _4 = _1;
-//            | Live variables at bb2[4]: [_4]
+//            | Live variables on entry to bb2[4]: [_4]
 //        _3 = const use_x(move _4) -> [return: bb3, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/liveness-interblock.rs b/src/test/mir-opt/nll/liveness-interblock.rs
index 5d799d3d90b..671f5e5292a 100644
--- a/src/test/mir-opt/nll/liveness-interblock.rs
+++ b/src/test/mir-opt/nll/liveness-interblock.rs
@@ -31,18 +31,18 @@ fn main() {
 // START rustc.main.nll.0.mir
 //     | Live variables on entry to bb3: [_1]
 //     bb3: {
-//             | Live variables at bb3[0]: [_1]
+//             | Live variables on entry to bb3[0]: [_1]
 //         StorageLive(_4);
-//             | Live variables at bb3[1]: [_1]
+//             | Live variables on entry to bb3[1]: [_1]
 //         _4 = _1;
-//             | Live variables at bb3[2]: [_4]
+//             | Live variables on entry to bb3[2]: [_4]
 //         _3 = const make_live(move _4) -> [return: bb5, unwind: bb1];
 //     }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //     | Live variables on entry to bb4: []
 //     bb4: {
-//             | Live variables at bb4[0]: []
+//             | Live variables on entry to bb4[0]: []
 //         _5 = const make_dead() -> [return: bb6, unwind: bb1];
 //     }
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs
index 7039de727fa..0c42585a528 100644
--- a/src/test/mir-opt/nll/named-lifetimes-basic.rs
+++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs
@@ -26,9 +26,18 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.use_x.nll.0.mir
-// | '_#0r: {bb0[0], bb0[1], '_#0r}
-// | '_#1r: {bb0[0], bb0[1], '_#1r}
-// | '_#2r: {bb0[0], bb0[1], '_#2r}
-// | '_#3r: {bb0[0], bb0[1], '_#3r}
+// | Free Region Mapping
+// | '_#0r    | Global   | ['_#2r, '_#1r, '_#0r, '_#3r]
+// | '_#1r    | External | ['_#1r]
+// | '_#2r    | External | ['_#2r, '_#1r]
+// | '_#3r    | Local    | ['_#3r]
+// |
+// | Inferred Region Values
+// | '_#0r    | {bb0[0], bb0[1], '_#0r}
+// | '_#1r    | {bb0[0], bb0[1], '_#1r}
+// | '_#2r    | {bb0[0], bb0[1], '_#2r}
+// | '_#3r    | {bb0[0], bb0[1], '_#3r}
+// |
+// ...
 // fn use_x(_1: &'_#1r mut i32, _2: &'_#2r u32, _3: &'_#1r u32, _4: &'_#3r u32) -> bool {
 // END rustc.use_x.nll.0.mir
diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs
index f51e839e4fc..d203472f20c 100644
--- a/src/test/mir-opt/nll/reborrow-basic.rs
+++ b/src/test/mir-opt/nll/reborrow-basic.rs
@@ -28,11 +28,10 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#6r: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// | '_#6r    | {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// ...
+// | '_#8r    | {bb0[11], bb0[12], bb0[13], bb0[14]}
 // ...
-// | '_#8r: {bb0[11], bb0[12], bb0[13], bb0[14]}
-// END rustc.main.nll.0.mir
-// START rustc.main.nll.0.mir
 // let _2: &'_#6r mut i32;
 // ...
 // let _4: &'_#8r mut i32;
diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs
index cfbc51f9e18..c04cedbc04b 100644
--- a/src/test/mir-opt/nll/region-liveness-basic.rs
+++ b/src/test/mir-opt/nll/region-liveness-basic.rs
@@ -31,26 +31,26 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]}
-// | '_#2r: {bb2[1], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[1], bb3[0], bb3[1]}
 // ...
 //             let _2: &'_#2r usize;
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    bb2: {
-//            | Live variables at bb2[0]: [_1, _3]
+//            | Live variables on entry to bb2[0]: [_1, _3]
 //        _2 = &'_#1r _1[_3];
-//            | Live variables at bb2[1]: [_2]
+//            | Live variables on entry to bb2[1]: [_2]
 //        switchInt(const true) -> [0u8: bb4, otherwise: bb3];
 //    }
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 //    bb3: {
-//            | Live variables at bb3[0]: [_2]
+//            | Live variables on entry to bb3[0]: [_2]
 //        StorageLive(_7);
-//            | Live variables at bb3[1]: [_2]
+//            | Live variables on entry to bb3[1]: [_2]
 //        _7 = (*_2);
-//            | Live variables at bb3[2]: [_7]
+//            | Live variables on entry to bb3[2]: [_7]
 //        _6 = const use_x(move _7) -> [return: bb5, unwind: bb1];
 //    }
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
index 04a30dc284d..e2ad49a4436 100644
--- a/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
+++ b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
@@ -44,5 +44,5 @@ unsafe impl<#[may_dangle] T> Drop for Wrap<T> {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
+// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1]}
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
index 5569fe7f574..e0272a51d03 100644
--- a/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
+++ b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
@@ -46,5 +46,5 @@ impl<T> Drop for Wrap<T> {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#5r: {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
+// | '_#5r    | {bb2[3], bb2[4], bb2[5], bb3[0], bb3[1], bb3[2], bb4[0], bb5[0], bb5[1], bb5[2], bb6[0], bb7[0], bb7[1], bb8[0]}
 // END rustc.main.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
index 679f31fdab9..8aa0eb1a3a9 100644
--- a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
+++ b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
@@ -36,10 +36,10 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb3[0], bb3[1]}
 // ...
-// | '_#3r: {bb8[1], bb8[2], bb8[3], bb8[4]}
-// | '_#4r: {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
+// | '_#3r    | {bb8[1], bb8[2], bb8[3], bb8[4]}
+// | '_#4r    | {bb2[1], bb3[0], bb3[1], bb8[2], bb8[3], bb8[4]}
 // ...
 // let mut _2: &'_#4r usize;
 // ...
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
index 471d77aefac..2bc165bd3c4 100644
--- a/src/test/mir-opt/nll/region-subtyping-basic.rs
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -32,9 +32,9 @@ fn main() {
 
 // END RUST SOURCE
 // START rustc.main.nll.0.mir
-// | '_#1r: {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#2r: {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
-// | '_#3r: {bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#1r    | {bb2[0], bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#2r    | {bb2[1], bb2[2], bb2[3], bb2[4], bb2[5], bb2[6], bb3[0], bb3[1]}
+// | '_#3r    | {bb2[5], bb2[6], bb3[0], bb3[1]}
 // END rustc.main.nll.0.mir
 // START rustc.main.nll.0.mir
 // let _2: &'_#2r usize;
diff --git a/src/test/parse-fail/issue-17383.rs b/src/test/parse-fail/issue-17383.rs
index 1b33cb38857..48f629fd828 100644
--- a/src/test/parse-fail/issue-17383.rs
+++ b/src/test/parse-fail/issue-17383.rs
@@ -12,7 +12,7 @@
 
 enum X {
     A =
-        b'a' //~ ERROR discriminator values can only be used with a c-like enum
+        b'a' //~ ERROR discriminator values can only be used with a field-less enum
     ,
     B(isize)
 }
diff --git a/src/test/parse-fail/tag-variant-disr-non-nullary.rs b/src/test/parse-fail/tag-variant-disr-non-nullary.rs
index f90b1cc94bb..2d86589285c 100644
--- a/src/test/parse-fail/tag-variant-disr-non-nullary.rs
+++ b/src/test/parse-fail/tag-variant-disr-non-nullary.rs
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z parse-only
 
-//error-pattern: discriminator values can only be used with a c-like enum
+//error-pattern: discriminator values can only be used with a field-less enum
 
 enum color {
     red = 0xff0000,
diff --git a/src/test/run-pass/abi-sysv64-arg-passing.rs b/src/test/run-pass/abi-sysv64-arg-passing.rs
index 23dd0603184..4ec3f16f7af 100644
--- a/src/test/run-pass/abi-sysv64-arg-passing.rs
+++ b/src/test/run-pass/abi-sysv64-arg-passing.rs
@@ -39,7 +39,6 @@
 
 // note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows
 
-#![feature(abi_sysv64)]
 #[allow(dead_code)]
 #[allow(improper_ctypes)]
 
diff --git a/src/test/run-pass/abi-sysv64-register-usage.rs b/src/test/run-pass/abi-sysv64-register-usage.rs
index 7e3b32122ac..1cae8671266 100644
--- a/src/test/run-pass/abi-sysv64-register-usage.rs
+++ b/src/test/run-pass/abi-sysv64-register-usage.rs
@@ -15,7 +15,6 @@
 // ignore-arm
 // ignore-aarch64
 
-#![feature(abi_sysv64)]
 #![feature(asm)]
 
 #[cfg(target_arch = "x86_64")]
diff --git a/src/test/run-pass/auxiliary/svh-a-comment.rs b/src/test/run-pass/auxiliary/svh-a-comment.rs
deleted file mode 100644
index 22e40822eec..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-comment.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-pub fn foo<T:U>(_: isize) -> isize {
-    // a comment does not affect the svh
-    3
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/auxiliary/svh-a-doc.rs b/src/test/run-pass/auxiliary/svh-a-doc.rs
deleted file mode 100644
index 3d8a728967a..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-doc.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-// Adding some documentation does not affect the svh.
-
-/// foo always returns three.
-pub fn foo<T:U>(_: isize) -> isize {
-    3
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/auxiliary/svh-a-macro.rs b/src/test/run-pass/auxiliary/svh-a-macro.rs
deleted file mode 100644
index 41d7eb7b186..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-macro.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-pub fn foo<T:U>(_: isize) -> isize {
-    // a macro invocation in a function body does not affect the svh,
-    // as long as it yields the same code.
-    three!()
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/auxiliary/svh-a-no-change.rs b/src/test/run-pass/auxiliary/svh-a-no-change.rs
deleted file mode 100644
index 31a97f695f0..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-no-change.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-pub fn foo<T:U>(_: isize) -> isize {
-    3
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs b/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs
deleted file mode 100644
index e405c337abe..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-redundant-cfg.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-// cfg attribute does not affect the svh, as long as it yields the same code.
-#[cfg(not(an_unused_name))]
-pub fn foo<T:U>(_: isize) -> isize {
-    3
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/auxiliary/svh-a-whitespace.rs b/src/test/run-pass/auxiliary/svh-a-whitespace.rs
deleted file mode 100644
index 9ef788c9842..00000000000
--- a/src/test/run-pass/auxiliary/svh-a-whitespace.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The `svh-a-*.rs` files are all deviations from the base file
-//! svh-a-base.rs with some difference (usually in `fn foo`) that
-//! should not affect the strict version hash (SVH) computation
-//! (#14132).
-
-#![crate_name = "a"]
-
-macro_rules! three {
-    () => { 3 }
-}
-
-pub trait U {}
-pub trait V {}
-impl U for () {}
-impl V for () {}
-
-static A_CONSTANT : isize = 2;
-
-pub fn foo<T:U>(_: isize) -> isize {
-
-    3
-
-}
-
-pub fn an_unused_name() -> isize {
-    4
-}
diff --git a/src/test/run-pass/hygiene/issue-44128.rs b/src/test/run-pass/hygiene/issue-44128.rs
new file mode 100644
index 00000000000..213ee1edff4
--- /dev/null
+++ b/src/test/run-pass/hygiene/issue-44128.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+pub macro create_struct($a:ident) {
+    struct $a;
+    impl Clone for $a {
+        fn clone(&self) -> Self {
+            $a
+        }
+    }
+}
+
+fn main() {
+    create_struct!(Test);
+    Test.clone();
+}
diff --git a/src/test/run-pass/issue-44373.rs b/src/test/run-pass/issue-44373.rs
index 06627e2ad93..d0f8ed96f4c 100644
--- a/src/test/run-pass/issue-44373.rs
+++ b/src/test/run-pass/issue-44373.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z borrowck=compare
+
 struct Foo(bool);
 
 struct Container(&'static [&'static Foo]);
diff --git a/src/test/run-pass/match-pipe-binding.rs b/src/test/run-pass/match-pipe-binding.rs
index bda90d3aaec..9592da77a1b 100644
--- a/src/test/run-pass/match-pipe-binding.rs
+++ b/src/test/run-pass/match-pipe-binding.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: -Z borrowck=compare
 
 fn test1() {
     // from issue 6338
diff --git a/src/test/run-pass/svh-add-doc.rs b/src/test/run-pass/svh-add-doc.rs
deleted file mode 100644
index ea07ebe3646..00000000000
--- a/src/test/run-pass/svh-add-doc.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// note that these aux-build directives must be in this order
-// aux-build:svh-a-base.rs
-// aux-build:svh-b.rs
-// aux-build:svh-a-doc.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate a;
-extern crate b;
-
-fn main() {
-    b::foo()
-}
diff --git a/src/test/run-pass/svh-add-macro.rs b/src/test/run-pass/svh-add-macro.rs
deleted file mode 100644
index 4e0192c40c2..00000000000
--- a/src/test/run-pass/svh-add-macro.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// note that these aux-build directives must be in this order
-// aux-build:svh-a-base.rs
-// aux-build:svh-b.rs
-// aux-build:svh-a-macro.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate a;
-extern crate b;
-
-fn main() {
-    b::foo()
-}
diff --git a/src/test/run-pass/svh-add-nothing.rs b/src/test/run-pass/svh-add-nothing.rs
index 9aa56ed2a76..aca50859b6e 100644
--- a/src/test/run-pass/svh-add-nothing.rs
+++ b/src/test/run-pass/svh-add-nothing.rs
@@ -11,7 +11,7 @@
 // note that these aux-build directives must be in this order
 // aux-build:svh-a-base.rs
 // aux-build:svh-b.rs
-// aux-build:svh-a-no-change.rs
+// aux-build:svh-a-base.rs
 
 // pretty-expanded FIXME #23616
 
diff --git a/src/test/run-pass/svh-add-redundant-cfg.rs b/src/test/run-pass/svh-add-redundant-cfg.rs
deleted file mode 100644
index 2da3004aaf1..00000000000
--- a/src/test/run-pass/svh-add-redundant-cfg.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// note that these aux-build directives must be in this order
-// aux-build:svh-a-base.rs
-// aux-build:svh-b.rs
-// aux-build:svh-a-redundant-cfg.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate a;
-extern crate b;
-
-fn main() {
-    b::foo()
-}
diff --git a/src/test/run-pass/svh-add-whitespace.rs b/src/test/run-pass/svh-add-whitespace.rs
deleted file mode 100644
index bfc676bde26..00000000000
--- a/src/test/run-pass/svh-add-whitespace.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// note that these aux-build directives must be in this order
-// aux-build:svh-a-base.rs
-// aux-build:svh-b.rs
-// aux-build:svh-a-whitespace.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate a;
-extern crate b;
-
-fn main() {
-    b::foo()
-}
diff --git a/src/test/run-pass/svh-add-comment.rs b/src/test/run-pass/thinlto/weak-works.rs
index 4d7b61e08f5..b9719e04f34 100644
--- a/src/test/run-pass/svh-add-comment.rs
+++ b/src/test/run-pass/thinlto/weak-works.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,16 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// note that these aux-build directives must be in this order
-// aux-build:svh-a-base.rs
-// aux-build:svh-b.rs
-// aux-build:svh-a-comment.rs
+// compile-flags: -C codegen-units=8 -Z thinlto
+// ignore-windows
+// min-llvm-version 4.0
 
-// pretty-expanded FIXME #23616
+#![feature(linkage)]
 
-extern crate a;
-extern crate b;
+pub mod foo {
+    #[linkage = "weak"]
+    #[no_mangle]
+    pub extern "C" fn FOO() -> i32 {
+        0
+    }
+}
+
+mod bar {
+    extern "C" {
+        fn FOO() -> i32;
+    }
+
+    pub fn bar() -> i32 {
+        unsafe { FOO() }
+    }
+}
 
 fn main() {
-    b::foo()
+    bar::bar();
 }
diff --git a/src/test/compile-fail/auxiliary/cfg-target-thread-local.rs b/src/test/ui/auxiliary/cfg-target-thread-local.rs
index d1971a5e1ae..d1971a5e1ae 100644
--- a/src/test/compile-fail/auxiliary/cfg-target-thread-local.rs
+++ b/src/test/ui/auxiliary/cfg-target-thread-local.rs
diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr
index 41ab60f017f..e95078f2547 100644
--- a/src/test/ui/codemap_tests/tab.stderr
+++ b/src/test/ui/codemap_tests/tab.stderr
@@ -1,16 +1,16 @@
 error[E0425]: cannot find value `bar` in this scope
   --> $DIR/tab.rs:14:2
    |
-14 |  bar; //~ ERROR cannot find value `bar`
-   |  ^^^ not found in this scope
+14 |     bar; //~ ERROR cannot find value `bar`
+   |     ^^^ not found in this scope
 
 error[E0308]: mismatched types
   --> $DIR/tab.rs:18:2
    |
 17 | fn foo() {
    |          - help: try adding a return type: `-> &'static str `
-18 |  "bar   boo" //~ ERROR mismatched types
-   |  ^^^^^^^^^^^ expected (), found reference
+18 |     "bar            boo" //~ ERROR mismatched types
+   |     ^^^^^^^^^^^^^^^^^^^^ expected (), found reference
    |
    = note: expected type `()`
               found type `&'static str`
diff --git a/src/test/ui/codemap_tests/tab_2.stderr b/src/test/ui/codemap_tests/tab_2.stderr
index 7f6b55e7eb8..34c49d97562 100644
--- a/src/test/ui/codemap_tests/tab_2.stderr
+++ b/src/test/ui/codemap_tests/tab_2.stderr
@@ -1,8 +1,8 @@
 error: unterminated double quote string
   --> $DIR/tab_2.rs:14:7
    |
-14 |       """; //~ ERROR unterminated double quote
-   |  _______^
+14 |                   """; //~ ERROR unterminated double quote
+   |  ___________________^
 15 | | }
    | |__^
 
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 278e590a36d..32202062663 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -1,11 +1,11 @@
 error[E0382]: use of moved value: `some_vec`
   --> $DIR/tab_3.rs:17:20
    |
-15 |  some_vec.into_iter();
-   |  -------- value moved here
-16 |  {
-17 |   println!("{:?}", some_vec); //~ ERROR use of moved
-   |                    ^^^^^^^^ value used here after move
+15 |     some_vec.into_iter();
+   |     -------- value moved here
+16 |     {
+17 |         println!("{:?}", some_vec); //~ ERROR use of moved
+   |                          ^^^^^^^^ value used here after move
    |
    = note: move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
 
diff --git a/src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs b/src/test/ui/feature-gate-abi-msp430-interrupt.rs
index 030e37475c0..030e37475c0 100644
--- a/src/test/compile-fail/feature-gate-abi-msp430-interrupt.rs
+++ b/src/test/ui/feature-gate-abi-msp430-interrupt.rs
diff --git a/src/test/ui/feature-gate-abi-msp430-interrupt.stderr b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr
new file mode 100644
index 00000000000..b05be6e4391
--- /dev/null
+++ b/src/test/ui/feature-gate-abi-msp430-interrupt.stderr
@@ -0,0 +1,10 @@
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi-msp430-interrupt.rs:14:1
+   |
+14 | extern "msp430-interrupt" fn foo() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/ui/feature-gate-abi.rs
index 45c715f51fe..45c715f51fe 100644
--- a/src/test/compile-fail/feature-gate-abi.rs
+++ b/src/test/ui/feature-gate-abi.rs
diff --git a/src/test/ui/feature-gate-abi.stderr b/src/test/ui/feature-gate-abi.stderr
new file mode 100644
index 00000000000..7d2ad0be391
--- /dev/null
+++ b/src/test/ui/feature-gate-abi.stderr
@@ -0,0 +1,450 @@
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:19:1
+   |
+19 | extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:20:1
+   |
+20 | extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:21:1
+   |
+21 | extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:22:1
+   |
+22 | extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:23:1
+   |
+23 | extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:24:1
+   |
+24 | extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:25:1
+   |
+25 | extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:26:1
+   |
+26 | extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:30:5
+   |
+30 |     extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:31:5
+   |
+31 |     extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:32:5
+   |
+32 |     extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:33:5
+   |
+33 |     extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:34:5
+   |
+34 |     extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:35:5
+   |
+35 |     extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:36:5
+   |
+36 |     extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:37:5
+   |
+37 |     extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:39:5
+   |
+39 |     extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:40:5
+   |
+40 |     extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:41:5
+   |
+41 |     extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:42:5
+   |
+42 |     extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:43:5
+   |
+43 |     extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:44:5
+   |
+44 |     extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:45:5
+   |
+45 |     extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:46:5
+   |
+46 |     extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:53:5
+   |
+53 |     extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:54:5
+   |
+54 |     extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:55:5
+   |
+55 |     extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:56:5
+   |
+56 |     extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:57:5
+   |
+57 |     extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:58:5
+   |
+58 |     extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:59:5
+   |
+59 |     extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:60:5
+   |
+60 |     extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:65:5
+   |
+65 |     extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:66:5
+   |
+66 |     extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:67:5
+   |
+67 |     extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:68:5
+   |
+68 |     extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:69:5
+   |
+69 |     extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:70:5
+   |
+70 |     extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:71:5
+   |
+71 |     extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:72:5
+   |
+72 |     extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:76:11
+   |
+76 | type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:77:11
+   |
+77 | type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:78:11
+   |
+78 | type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:79:11
+   |
+79 | type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:80:11
+   |
+80 | type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:81:11
+   |
+81 | type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:82:11
+   |
+82 | type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:83:11
+   |
+83 | type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
+   |           ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-abi.rs:86:1
+   |
+86 | extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: platform intrinsics are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-abi.rs:87:1
+   |
+87 | extern "platform-intrinsic" {} //~ ERROR platform intrinsics are experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(platform_intrinsics)] to the crate attributes to enable
+
+error: vectorcall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:88:1
+   |
+88 | extern "vectorcall" {} //~ ERROR vectorcall is experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_vectorcall)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-abi.rs:89:1
+   |
+89 | extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: msp430-interrupt ABI is experimental and subject to change (see issue #38487)
+  --> $DIR/feature-gate-abi.rs:90:1
+   |
+90 | extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_msp430_interrupt)] to the crate attributes to enable
+
+error: PTX ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:91:1
+   |
+91 | extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_ptx)] to the crate attributes to enable
+
+error: x86-interrupt ABI is experimental and subject to change (see issue #40180)
+  --> $DIR/feature-gate-abi.rs:92:1
+   |
+92 | extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable
+
+error: thiscall is experimental and subject to change
+  --> $DIR/feature-gate-abi.rs:93:1
+   |
+93 | extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(abi_thiscall)] to the crate attributes to enable
+
+error: aborting due to 56 previous errors
+
diff --git a/src/test/compile-fail/unadjusted-unstable.rs b/src/test/ui/feature-gate-abi_unadjusted.rs
index 2c23050085d..501f4451ed8 100644
--- a/src/test/compile-fail/unadjusted-unstable.rs
+++ b/src/test/ui/feature-gate-abi_unadjusted.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-abi_unadjusted
-
 extern "unadjusted" fn foo() {
 //~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
 }
diff --git a/src/test/ui/feature-gate-abi_unadjusted.stderr b/src/test/ui/feature-gate-abi_unadjusted.stderr
new file mode 100644
index 00000000000..3cc43847156
--- /dev/null
+++ b/src/test/ui/feature-gate-abi_unadjusted.stderr
@@ -0,0 +1,12 @@
+error: unadjusted ABI is an implementation detail and perma-unstable
+  --> $DIR/feature-gate-abi_unadjusted.rs:11:1
+   |
+11 | / extern "unadjusted" fn foo() {
+12 | | //~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
+13 | | }
+   | |_^
+   |
+   = help: add #![feature(abi_unadjusted)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-advanced-slice-features.rs b/src/test/ui/feature-gate-advanced-slice-features.rs
index dc9b4e634ab..dc9b4e634ab 100644
--- a/src/test/compile-fail/feature-gate-advanced-slice-features.rs
+++ b/src/test/ui/feature-gate-advanced-slice-features.rs
diff --git a/src/test/ui/feature-gate-advanced-slice-features.stderr b/src/test/ui/feature-gate-advanced-slice-features.stderr
new file mode 100644
index 00000000000..815593d07a5
--- /dev/null
+++ b/src/test/ui/feature-gate-advanced-slice-features.stderr
@@ -0,0 +1,18 @@
+error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+  --> $DIR/feature-gate-advanced-slice-features.rs:18:9
+   |
+18 |         [ xs.., 4, 5 ] => {}    //~ ERROR multiple-element slice matches
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
+
+error: multiple-element slice matches anywhere but at the end of a slice (e.g. `[0, ..xs, 0]`) are experimental (see issue #23121)
+  --> $DIR/feature-gate-advanced-slice-features.rs:19:9
+   |
+19 |         [ 1, xs.., 5 ] => {}    //~ ERROR multiple-element slice matches
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(advanced_slice_patterns)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-allocator_internals.rs b/src/test/ui/feature-gate-allocator_internals.rs
index b519a985ec5..b519a985ec5 100644
--- a/src/test/compile-fail/feature-gate-allocator_internals.rs
+++ b/src/test/ui/feature-gate-allocator_internals.rs
diff --git a/src/test/ui/feature-gate-allocator_internals.stderr b/src/test/ui/feature-gate-allocator_internals.stderr
new file mode 100644
index 00000000000..f1f4705b3bb
--- /dev/null
+++ b/src/test/ui/feature-gate-allocator_internals.stderr
@@ -0,0 +1,10 @@
+error: the `#[default_lib_allocator]` attribute is an experimental feature
+  --> $DIR/feature-gate-allocator_internals.rs:11:1
+   |
+11 | #![default_lib_allocator] //~ ERROR: attribute is an experimental feature
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allocator_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-allow-internal-unsafe-nested-macro.rs b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.rs
index 590dc619f2f..590dc619f2f 100644
--- a/src/test/compile-fail/feature-gate-allow-internal-unsafe-nested-macro.rs
+++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.rs
diff --git a/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr
new file mode 100644
index 00000000000..40bdde37ee8
--- /dev/null
+++ b/src/test/ui/feature-gate-allow-internal-unsafe-nested-macro.stderr
@@ -0,0 +1,13 @@
+error: allow_internal_unsafe side-steps the unsafe_code lint
+  --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:18:9
+   |
+18 |         #[allow_internal_unsafe] //~ ERROR allow_internal_unsafe side-steps
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+25 | bar!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(allow_internal_unsafe)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.rs
index 9af501b1419..9af501b1419 100644
--- a/src/test/compile-fail/feature-gate-allow-internal-unstable-nested-macro.rs
+++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.rs
diff --git a/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr
new file mode 100644
index 00000000000..60d72fbc3b3
--- /dev/null
+++ b/src/test/ui/feature-gate-allow-internal-unstable-nested-macro.stderr
@@ -0,0 +1,13 @@
+error: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:18:9
+   |
+18 |         #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+25 | bar!();
+   | ------- in this macro invocation
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable-struct.rs b/src/test/ui/feature-gate-allow-internal-unstable-struct.rs
index b186278ef8b..b186278ef8b 100644
--- a/src/test/compile-fail/feature-gate-allow-internal-unstable-struct.rs
+++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.rs
diff --git a/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr
new file mode 100644
index 00000000000..2fb86ce8f4e
--- /dev/null
+++ b/src/test/ui/feature-gate-allow-internal-unstable-struct.stderr
@@ -0,0 +1,10 @@
+error: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable-struct.rs:14:1
+   |
+14 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-allow-internal-unstable.rs b/src/test/ui/feature-gate-allow-internal-unstable.rs
index 61a362cb37f..61a362cb37f 100644
--- a/src/test/compile-fail/feature-gate-allow-internal-unstable.rs
+++ b/src/test/ui/feature-gate-allow-internal-unstable.rs
diff --git a/src/test/ui/feature-gate-allow-internal-unstable.stderr b/src/test/ui/feature-gate-allow-internal-unstable.stderr
new file mode 100644
index 00000000000..a5740a1a789
--- /dev/null
+++ b/src/test/ui/feature-gate-allow-internal-unstable.stderr
@@ -0,0 +1,10 @@
+error: allow_internal_unstable side-steps feature gating and stability checks
+  --> $DIR/feature-gate-allow-internal-unstable.rs:13:1
+   |
+13 | #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_internal_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/ui/feature-gate-allow_fail.rs
index 11247402809..11247402809 100644
--- a/src/test/compile-fail/feature-gate-allow_fail.rs
+++ b/src/test/ui/feature-gate-allow_fail.rs
diff --git a/src/test/ui/feature-gate-allow_fail.stderr b/src/test/ui/feature-gate-allow_fail.stderr
new file mode 100644
index 00000000000..65cd137459a
--- /dev/null
+++ b/src/test/ui/feature-gate-allow_fail.stderr
@@ -0,0 +1,10 @@
+error: allow_fail attribute is currently unstable (see issue #42219)
+  --> $DIR/feature-gate-allow_fail.rs:13:1
+   |
+13 | #[allow_fail] //~ ERROR allow_fail attribute is currently unstable
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allow_fail)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs b/src/test/ui/feature-gate-arbitrary-self-types.rs
index ff0306f1993..ff0306f1993 100644
--- a/src/test/compile-fail/feature-gate-arbitrary-self-types.rs
+++ b/src/test/ui/feature-gate-arbitrary-self-types.rs
diff --git a/src/test/ui/feature-gate-arbitrary-self-types.stderr b/src/test/ui/feature-gate-arbitrary-self-types.stderr
new file mode 100644
index 00000000000..2ef517cc9e1
--- /dev/null
+++ b/src/test/ui/feature-gate-arbitrary-self-types.stderr
@@ -0,0 +1,29 @@
+error: arbitrary `self` types are unstable (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:14:18
+   |
+14 |     fn foo(self: Rc<Box<Self>>); //~ ERROR arbitrary `self` types are unstable
+   |                  ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: arbitrary `self` types are unstable (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:20:18
+   |
+20 |     fn foo(self: Rc<Box<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+   |                  ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: arbitrary `self` types are unstable (see issue #44874)
+  --> $DIR/feature-gate-arbitrary-self-types.rs:24:18
+   |
+24 |     fn bar(self: Box<Rc<Self>>) {} //~ ERROR arbitrary `self` types are unstable
+   |                  ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(arbitrary_self_types)] to the crate attributes to enable
+   = help: consider changing to `self`, `&self`, `&mut self`, or `self: Box<Self>`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/asm-gated.rs b/src/test/ui/feature-gate-asm.rs
index cd9cc223701..8d053bdae78 100644
--- a/src/test/compile-fail/asm-gated.rs
+++ b/src/test/ui/feature-gate-asm.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-asm
-
 fn main() {
     unsafe {
         asm!(""); //~ ERROR inline assembly is not stable enough
diff --git a/src/test/ui/feature-gate-asm.stderr b/src/test/ui/feature-gate-asm.stderr
new file mode 100644
index 00000000000..ff68a4fb23e
--- /dev/null
+++ b/src/test/ui/feature-gate-asm.stderr
@@ -0,0 +1,10 @@
+error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+  --> $DIR/feature-gate-asm.rs:13:9
+   |
+13 |         asm!(""); //~ ERROR inline assembly is not stable enough
+   |         ^^^^^^^^^
+   |
+   = help: add #![feature(asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/asm-gated2.rs b/src/test/ui/feature-gate-asm2.rs
index 222190de9fe..222190de9fe 100644
--- a/src/test/compile-fail/asm-gated2.rs
+++ b/src/test/ui/feature-gate-asm2.rs
diff --git a/src/test/ui/feature-gate-asm2.stderr b/src/test/ui/feature-gate-asm2.stderr
new file mode 100644
index 00000000000..1e02cede61d
--- /dev/null
+++ b/src/test/ui/feature-gate-asm2.stderr
@@ -0,0 +1,10 @@
+error: inline assembly is not stable enough for use and is subject to change (see issue #29722)
+  --> $DIR/feature-gate-asm2.rs:15:24
+   |
+15 |         println!("{}", asm!("")); //~ ERROR inline assembly is not stable
+   |                        ^^^^^^^^
+   |
+   = help: add #![feature(asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs b/src/test/ui/feature-gate-assoc-type-defaults.rs
index de3521eb0f2..de3521eb0f2 100644
--- a/src/test/compile-fail/feature-gate-assoc-type-defaults.rs
+++ b/src/test/ui/feature-gate-assoc-type-defaults.rs
diff --git a/src/test/ui/feature-gate-assoc-type-defaults.stderr b/src/test/ui/feature-gate-assoc-type-defaults.stderr
new file mode 100644
index 00000000000..5e288469168
--- /dev/null
+++ b/src/test/ui/feature-gate-assoc-type-defaults.stderr
@@ -0,0 +1,10 @@
+error: associated type defaults are unstable (see issue #29661)
+  --> $DIR/feature-gate-assoc-type-defaults.rs:14:5
+   |
+14 |     type Bar = u8; //~ ERROR associated type defaults are unstable
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(associated_type_defaults)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-box-expr.rs b/src/test/ui/feature-gate-box-expr.rs
index 65d437d0c0d..65d437d0c0d 100644
--- a/src/test/compile-fail/feature-gate-box-expr.rs
+++ b/src/test/ui/feature-gate-box-expr.rs
diff --git a/src/test/ui/feature-gate-box-expr.stderr b/src/test/ui/feature-gate-box-expr.stderr
new file mode 100644
index 00000000000..cef5adbd15a
--- /dev/null
+++ b/src/test/ui/feature-gate-box-expr.stderr
@@ -0,0 +1,10 @@
+error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+  --> $DIR/feature-gate-box-expr.rs:22:13
+   |
+22 |     let x = box 'c'; //~ ERROR box expression syntax is experimental
+   |             ^^^^^^^
+   |
+   = help: add #![feature(box_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-box-pat.rs b/src/test/ui/feature-gate-box_patterns.rs
index c30f3952dbf..e64081823e7 100644
--- a/src/test/compile-fail/feature-gate-box-pat.rs
+++ b/src/test/ui/feature-gate-box_patterns.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-box_patterns
-
 fn main() {
     let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
     println!("x: {}", x);
diff --git a/src/test/ui/feature-gate-box_patterns.stderr b/src/test/ui/feature-gate-box_patterns.stderr
new file mode 100644
index 00000000000..0a30de58a1f
--- /dev/null
+++ b/src/test/ui/feature-gate-box_patterns.stderr
@@ -0,0 +1,10 @@
+error: box pattern syntax is experimental (see issue #29641)
+  --> $DIR/feature-gate-box_patterns.rs:12:9
+   |
+12 |     let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
+   |         ^^^^^
+   |
+   = help: add #![feature(box_patterns)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/ui/feature-gate-box_syntax.rs
index 9a68ddb3059..a2643fe02b8 100644
--- a/src/test/compile-fail/gated-box-syntax.rs
+++ b/src/test/ui/feature-gate-box_syntax.rs
@@ -10,8 +10,6 @@
 
 // Test that the use of the box syntax is gated by `box_syntax` feature gate.
 
-// gate-test-box_syntax
-
 fn main() {
     let x = box 3;
     //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
diff --git a/src/test/ui/feature-gate-box_syntax.stderr b/src/test/ui/feature-gate-box_syntax.stderr
new file mode 100644
index 00000000000..9b21dd03051
--- /dev/null
+++ b/src/test/ui/feature-gate-box_syntax.stderr
@@ -0,0 +1,10 @@
+error: box expression syntax is experimental; you can call `Box::new` instead. (see issue #27779)
+  --> $DIR/feature-gate-box_syntax.rs:14:13
+   |
+14 |     let x = box 3;
+   |             ^^^^^
+   |
+   = help: add #![feature(box_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-catch_expr.rs b/src/test/ui/feature-gate-catch_expr.rs
index 5568a5cf0aa..5568a5cf0aa 100644
--- a/src/test/compile-fail/feature-gate-catch_expr.rs
+++ b/src/test/ui/feature-gate-catch_expr.rs
diff --git a/src/test/ui/feature-gate-catch_expr.stderr b/src/test/ui/feature-gate-catch_expr.stderr
new file mode 100644
index 00000000000..f486373d225
--- /dev/null
+++ b/src/test/ui/feature-gate-catch_expr.stderr
@@ -0,0 +1,14 @@
+error: `catch` expression is experimental (see issue #31436)
+  --> $DIR/feature-gate-catch_expr.rs:12:24
+   |
+12 |       let catch_result = do catch { //~ ERROR `catch` expression is experimental
+   |  ________________________^
+13 | |         let x = 5;
+14 | |         x
+15 | |     };
+   | |_____^
+   |
+   = help: add #![feature(catch_expr)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-cfg-target-feature.rs b/src/test/ui/feature-gate-cfg-target-feature.rs
index 7832e1c7c51..7832e1c7c51 100644
--- a/src/test/compile-fail/feature-gate-cfg-target-feature.rs
+++ b/src/test/ui/feature-gate-cfg-target-feature.rs
diff --git a/src/test/ui/feature-gate-cfg-target-feature.stderr b/src/test/ui/feature-gate-cfg-target-feature.stderr
new file mode 100644
index 00000000000..60dc6fbb57e
--- /dev/null
+++ b/src/test/ui/feature-gate-cfg-target-feature.stderr
@@ -0,0 +1,34 @@
+error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+  --> $DIR/feature-gate-cfg-target-feature.rs:12:12
+   |
+12 | #[cfg_attr(target_feature = "x", x)] //~ ERROR `cfg(target_feature)` is experimental
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
+
+error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+  --> $DIR/feature-gate-cfg-target-feature.rs:11:7
+   |
+11 | #[cfg(target_feature = "x")] //~ ERROR `cfg(target_feature)` is experimental
+   |       ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
+
+error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+  --> $DIR/feature-gate-cfg-target-feature.rs:15:19
+   |
+15 | #[cfg(not(any(all(target_feature = "x"))))] //~ ERROR `cfg(target_feature)` is experimental
+   |                   ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
+
+error: `cfg(target_feature)` is experimental and subject to change (see issue #29717)
+  --> $DIR/feature-gate-cfg-target-feature.rs:19:10
+   |
+19 |     cfg!(target_feature = "x");
+   |          ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_feature)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gate-cfg-target-has-atomic.rs
index aa27f8922c0..aa27f8922c0 100644
--- a/src/test/compile-fail/feature-gate-cfg-target-has-atomic.rs
+++ b/src/test/ui/feature-gate-cfg-target-has-atomic.rs
diff --git a/src/test/ui/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr
new file mode 100644
index 00000000000..5daf5de7123
--- /dev/null
+++ b/src/test/ui/feature-gate-cfg-target-has-atomic.stderr
@@ -0,0 +1,122 @@
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:23:7
+   |
+23 | #[cfg(target_has_atomic = "8")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7
+   |
+29 | #[cfg(target_has_atomic = "8")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7
+   |
+34 | #[cfg(target_has_atomic = "16")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7
+   |
+39 | #[cfg(target_has_atomic = "16")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7
+   |
+44 | #[cfg(target_has_atomic = "32")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7
+   |
+49 | #[cfg(target_has_atomic = "32")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7
+   |
+54 | #[cfg(target_has_atomic = "64")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7
+   |
+59 | #[cfg(target_has_atomic = "64")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7
+   |
+64 | #[cfg(target_has_atomic = "ptr")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7
+   |
+69 | #[cfg(target_has_atomic = "ptr")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:76:10
+   |
+76 |     cfg!(target_has_atomic = "8");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:78:10
+   |
+78 |     cfg!(target_has_atomic = "16");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:80:10
+   |
+80 |     cfg!(target_has_atomic = "32");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:82:10
+   |
+82 |     cfg!(target_has_atomic = "64");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976)
+  --> $DIR/feature-gate-cfg-target-has-atomic.rs:84:10
+   |
+84 |     cfg!(target_has_atomic = "ptr");
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-cfg-target-thread-local.rs b/src/test/ui/feature-gate-cfg-target-thread-local.rs
index 985bd8320e0..985bd8320e0 100644
--- a/src/test/compile-fail/feature-gate-cfg-target-thread-local.rs
+++ b/src/test/ui/feature-gate-cfg-target-thread-local.rs
diff --git a/src/test/ui/feature-gate-cfg-target-thread-local.stderr b/src/test/ui/feature-gate-cfg-target-thread-local.stderr
new file mode 100644
index 00000000000..9e2eea6e0a4
--- /dev/null
+++ b/src/test/ui/feature-gate-cfg-target-thread-local.stderr
@@ -0,0 +1,10 @@
+error: `cfg(target_thread_local)` is experimental and subject to change (see issue #29594)
+  --> $DIR/feature-gate-cfg-target-thread-local.rs:19:16
+   |
+19 |     #[cfg_attr(target_thread_local, thread_local)]
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_thread_local)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-cfg-target-vendor.rs b/src/test/ui/feature-gate-cfg-target-vendor.rs
index e68a84d3553..e68a84d3553 100644
--- a/src/test/compile-fail/feature-gate-cfg-target-vendor.rs
+++ b/src/test/ui/feature-gate-cfg-target-vendor.rs
diff --git a/src/test/ui/feature-gate-cfg-target-vendor.stderr b/src/test/ui/feature-gate-cfg-target-vendor.stderr
new file mode 100644
index 00000000000..c5709600dba
--- /dev/null
+++ b/src/test/ui/feature-gate-cfg-target-vendor.stderr
@@ -0,0 +1,34 @@
+error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+  --> $DIR/feature-gate-cfg-target-vendor.rs:12:12
+   |
+12 | #[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
+
+error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+  --> $DIR/feature-gate-cfg-target-vendor.rs:11:7
+   |
+11 | #[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental
+   |       ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
+
+error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+  --> $DIR/feature-gate-cfg-target-vendor.rs:15:19
+   |
+15 | #[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental
+   |                   ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
+
+error: `cfg(target_vendor)` is experimental and subject to change (see issue #29718)
+  --> $DIR/feature-gate-cfg-target-vendor.rs:19:10
+   |
+19 |     cfg!(target_vendor = "x");
+   |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(cfg_target_vendor)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-clone-closures.rs b/src/test/ui/feature-gate-clone-closures.rs
index a15153ea7bf..a15153ea7bf 100644
--- a/src/test/compile-fail/feature-gate-clone-closures.rs
+++ b/src/test/ui/feature-gate-clone-closures.rs
diff --git a/src/test/ui/feature-gate-clone-closures.stderr b/src/test/ui/feature-gate-clone-closures.stderr
new file mode 100644
index 00000000000..3e07aa17440
--- /dev/null
+++ b/src/test/ui/feature-gate-clone-closures.stderr
@@ -0,0 +1,10 @@
+error[E0599]: no method named `clone` found for type `[closure@$DIR/feature-gate-clone-closures.rs:16:17: 18:6 a:_]` in the current scope
+  --> $DIR/feature-gate-clone-closures.rs:20:23
+   |
+20 |     let hello = hello.clone(); //~ ERROR no method named `clone` found for type
+   |                       ^^^^^
+   |
+   = note: hello is a function, perhaps you wish to call it
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-compiler-builtins.rs b/src/test/ui/feature-gate-compiler-builtins.rs
index f9334f1d3b0..f9334f1d3b0 100644
--- a/src/test/compile-fail/feature-gate-compiler-builtins.rs
+++ b/src/test/ui/feature-gate-compiler-builtins.rs
diff --git a/src/test/ui/feature-gate-compiler-builtins.stderr b/src/test/ui/feature-gate-compiler-builtins.stderr
new file mode 100644
index 00000000000..ebf42b2bdd8
--- /dev/null
+++ b/src/test/ui/feature-gate-compiler-builtins.stderr
@@ -0,0 +1,10 @@
+error: the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate which contains compiler-rt intrinsics and will never be stable
+  --> $DIR/feature-gate-compiler-builtins.rs:11:1
+   |
+11 | #![compiler_builtins] //~ ERROR the `#[compiler_builtins]` attribute is
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(compiler_builtins)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/concat_idents-gate.rs b/src/test/ui/feature-gate-concat_idents.rs
index 5b125d0e51c..f4d97445725 100644
--- a/src/test/compile-fail/concat_idents-gate.rs
+++ b/src/test/ui/feature-gate-concat_idents.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-concat_idents
-
 const XY_1: i32 = 10;
 
 fn main() {
diff --git a/src/test/ui/feature-gate-concat_idents.stderr b/src/test/ui/feature-gate-concat_idents.stderr
new file mode 100644
index 00000000000..c980668c298
--- /dev/null
+++ b/src/test/ui/feature-gate-concat_idents.stderr
@@ -0,0 +1,18 @@
+error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents.rs:15:13
+   |
+15 |     let a = concat_idents!(X, Y_1); //~ ERROR `concat_idents` is not stable
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents.rs:16:13
+   |
+16 |     let b = concat_idents!(X, Y_2); //~ ERROR `concat_idents` is not stable
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/gated-concat_idents.rs b/src/test/ui/feature-gate-concat_idents2.rs
index af288a97904..af288a97904 100644
--- a/src/test/compile-fail/gated-concat_idents.rs
+++ b/src/test/ui/feature-gate-concat_idents2.rs
diff --git a/src/test/ui/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gate-concat_idents2.stderr
new file mode 100644
index 00000000000..9cfd954eec8
--- /dev/null
+++ b/src/test/ui/feature-gate-concat_idents2.stderr
@@ -0,0 +1,10 @@
+error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents2.rs:14:5
+   |
+14 |     concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/concat_idents-gate2.rs b/src/test/ui/feature-gate-concat_idents3.rs
index 5a9ffe98c93..5a9ffe98c93 100644
--- a/src/test/compile-fail/concat_idents-gate2.rs
+++ b/src/test/ui/feature-gate-concat_idents3.rs
diff --git a/src/test/ui/feature-gate-concat_idents3.stderr b/src/test/ui/feature-gate-concat_idents3.stderr
new file mode 100644
index 00000000000..8399ca3c501
--- /dev/null
+++ b/src/test/ui/feature-gate-concat_idents3.stderr
@@ -0,0 +1,18 @@
+error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents3.rs:17:20
+   |
+17 |     assert_eq!(10, concat_idents!(X, Y_1)); //~ ERROR `concat_idents` is not stable
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: `concat_idents` is not stable enough for use and is subject to change (see issue #29599)
+  --> $DIR/feature-gate-concat_idents3.rs:18:20
+   |
+18 |     assert_eq!(20, concat_idents!(X, Y_2)); //~ ERROR `concat_idents` is not stable
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(concat_idents)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/impl-trait/feature-gate.rs b/src/test/ui/feature-gate-conservative_impl_trait.rs
index d46a16450db..7a3ae639bfc 100644
--- a/src/test/compile-fail/impl-trait/feature-gate.rs
+++ b/src/test/ui/feature-gate-conservative_impl_trait.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-conservative_impl_trait
-
 fn foo() -> impl Fn() { || {} }
 //~^ ERROR `impl Trait` in return position is experimental
 
diff --git a/src/test/ui/feature-gate-conservative_impl_trait.stderr b/src/test/ui/feature-gate-conservative_impl_trait.stderr
new file mode 100644
index 00000000000..72a4f52926a
--- /dev/null
+++ b/src/test/ui/feature-gate-conservative_impl_trait.stderr
@@ -0,0 +1,10 @@
+error: `impl Trait` in return position is experimental (see issue #34511)
+  --> $DIR/feature-gate-conservative_impl_trait.rs:11:13
+   |
+11 | fn foo() -> impl Fn() { || {} }
+   |             ^^^^^^^^^
+   |
+   = help: add #![feature(conservative_impl_trait)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-const-indexing.rs b/src/test/ui/feature-gate-const-indexing.rs
index 0d61878cd80..0d61878cd80 100644
--- a/src/test/compile-fail/feature-gate-const-indexing.rs
+++ b/src/test/ui/feature-gate-const-indexing.rs
diff --git a/src/test/ui/feature-gate-const-indexing.stderr b/src/test/ui/feature-gate-const-indexing.stderr
new file mode 100644
index 00000000000..bc4b687800d
--- /dev/null
+++ b/src/test/ui/feature-gate-const-indexing.stderr
@@ -0,0 +1,8 @@
+error[E0080]: constant evaluation error
+  --> $DIR/feature-gate-const-indexing.rs:16:24
+   |
+16 |     const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; //~ ERROR constant evaluation error
+   |                        ^^^^^^ the index operation on const values is unstable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/const-fn-stability.rs b/src/test/ui/feature-gate-const_fn.rs
index d093364497a..1d1dedddaaa 100644
--- a/src/test/compile-fail/const-fn-stability.rs
+++ b/src/test/ui/feature-gate-const_fn.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-const_fn
-
 // Test use of const fn without feature gate.
 
 const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
diff --git a/src/test/ui/feature-gate-const_fn.stderr b/src/test/ui/feature-gate-const_fn.stderr
new file mode 100644
index 00000000000..c62229ac71b
--- /dev/null
+++ b/src/test/ui/feature-gate-const_fn.stderr
@@ -0,0 +1,60 @@
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:16:5
+   |
+16 |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:18:5
+   |
+18 |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error[E0379]: trait fns cannot be declared const
+  --> $DIR/feature-gate-const_fn.rs:27:5
+   |
+27 |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^ trait fns cannot be const
+
+error: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-const_fn.rs:13:1
+   |
+13 | const fn foo() -> usize { 0 } //~ ERROR const fn is unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-const_fn.rs:16:5
+   |
+16 |     const fn foo() -> u32; //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-const_fn.rs:18:5
+   |
+18 |     const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-const_fn.rs:23:5
+   |
+23 |     const fn baz() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: const fn is unstable (see issue #24111)
+  --> $DIR/feature-gate-const_fn.rs:27:5
+   |
+27 |     const fn foo() -> u32 { 0 } //~ ERROR const fn is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_fn)] to the crate attributes to enable
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-copy-closures.rs b/src/test/ui/feature-gate-copy-closures.rs
index b11b09eb9fd..b11b09eb9fd 100644
--- a/src/test/compile-fail/feature-gate-copy-closures.rs
+++ b/src/test/ui/feature-gate-copy-closures.rs
diff --git a/src/test/ui/feature-gate-copy-closures.stderr b/src/test/ui/feature-gate-copy-closures.stderr
new file mode 100644
index 00000000000..9b324672f22
--- /dev/null
+++ b/src/test/ui/feature-gate-copy-closures.stderr
@@ -0,0 +1,12 @@
+error[E0382]: use of moved value: `hello`
+  --> $DIR/feature-gate-copy-closures.rs:18:9
+   |
+17 |     let b = hello;
+   |         - value moved here
+18 |     let c = hello; //~ ERROR use of moved value: `hello` [E0382]
+   |         ^ value used here after move
+   |
+   = note: move occurs because `hello` has type `[closure@$DIR/feature-gate-copy-closures.rs:13:17: 15:6 a:&i32]`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs b/src/test/ui/feature-gate-crate_in_paths.rs
index 830ec5959b7..830ec5959b7 100644
--- a/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs
+++ b/src/test/ui/feature-gate-crate_in_paths.rs
diff --git a/src/test/ui/feature-gate-crate_in_paths.stderr b/src/test/ui/feature-gate-crate_in_paths.stderr
new file mode 100644
index 00000000000..b13c82ecfc9
--- /dev/null
+++ b/src/test/ui/feature-gate-crate_in_paths.stderr
@@ -0,0 +1,10 @@
+error: `crate` in paths is experimental (see issue #45477)
+  --> $DIR/feature-gate-crate_in_paths.rs:14:15
+   |
+14 |     let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
+   |               ^^^^^
+   |
+   = help: add #![feature(crate_in_paths)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs b/src/test/ui/feature-gate-crate_visibility_modifier.rs
index a2937d6de31..a2937d6de31 100644
--- a/src/test/compile-fail/feature-gate-crate_visibility_modifier.rs
+++ b/src/test/ui/feature-gate-crate_visibility_modifier.rs
diff --git a/src/test/ui/feature-gate-crate_visibility_modifier.stderr b/src/test/ui/feature-gate-crate_visibility_modifier.stderr
new file mode 100644
index 00000000000..0862744b87b
--- /dev/null
+++ b/src/test/ui/feature-gate-crate_visibility_modifier.stderr
@@ -0,0 +1,10 @@
+error: `crate` visibility modifier is experimental (see issue #45388)
+  --> $DIR/feature-gate-crate_visibility_modifier.rs:11:1
+   |
+11 | crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
+   | ^^^^^
+   |
+   = help: add #![feature(crate_visibility_modifier)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/attr-literals.rs b/src/test/ui/feature-gate-custom_attribute.rs
index e77fde845ae..b5428803517 100644
--- a/src/test/compile-fail/attr-literals.rs
+++ b/src/test/ui/feature-gate-custom_attribute.rs
@@ -10,8 +10,6 @@
 
 // Check that literals in attributes parse just fine.
 
-// gate-test-custom_attribute
-
 #![feature(rustc_attrs, attr_literals)]
 #![allow(dead_code)]
 #![allow(unused_variables)]
diff --git a/src/test/ui/feature-gate-custom_attribute.stderr b/src/test/ui/feature-gate-custom_attribute.stderr
new file mode 100644
index 00000000000..866ebfe8f2f
--- /dev/null
+++ b/src/test/ui/feature-gate-custom_attribute.stderr
@@ -0,0 +1,106 @@
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:17:1
+   |
+17 | #[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:18:1
+   |
+18 | #[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:19:1
+   |
+19 | #[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:20:1
+   |
+20 | #[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:21:1
+   |
+21 | #[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:22:1
+   |
+22 | #[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:23:1
+   |
+23 | #[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:24:1
+   |
+24 | #[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:25:1
+   |
+25 | #[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:26:1
+   |
+26 | #[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:27:1
+   |
+27 | #[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:28:1
+   |
+28 | #[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `fake_doc` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute.rs:29:1
+   |
+29 | #[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 13 previous errors
+
diff --git a/src/test/compile-fail/attr-on-generic-formals-are-visited.rs b/src/test/ui/feature-gate-custom_attribute2.rs
index 0d89c52d885..0d89c52d885 100644
--- a/src/test/compile-fail/attr-on-generic-formals-are-visited.rs
+++ b/src/test/ui/feature-gate-custom_attribute2.rs
diff --git a/src/test/ui/feature-gate-custom_attribute2.stderr b/src/test/ui/feature-gate-custom_attribute2.stderr
new file mode 100644
index 00000000000..3e4ea58a7a3
--- /dev/null
+++ b/src/test/ui/feature-gate-custom_attribute2.stderr
@@ -0,0 +1,138 @@
+error: The attribute `lt_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:23:13
+   |
+23 | struct StLt<#[lt_struct] 'a>(&'a u32);
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_struct` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:25:13
+   |
+25 | struct StTy<#[ty_struct] I>(I);
+   |             ^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:28:11
+   |
+28 | enum EnLt<#[lt_enum] 'b> { A(&'b u32), B }
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_enum` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:30:11
+   |
+30 | enum EnTy<#[ty_enum] J> { A(J), B }
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:33:12
+   |
+33 | trait TrLt<#[lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+   |            ^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_trait` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:35:12
+   |
+35 | trait TrTy<#[ty_trait] K> { fn foo(&self, _: K); }
+   |            ^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:38:11
+   |
+38 | type TyLt<#[lt_type] 'd> = &'d u32;
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_type` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:40:11
+   |
+40 | type TyTy<#[ty_type] L> = (L, );
+   |           ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:43:6
+   |
+43 | impl<#[lt_inherent] 'e> StLt<'e> { }
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_inherent` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:45:6
+   |
+45 | impl<#[ty_inherent] M> StTy<M> { }
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:48:6
+   |
+48 | impl<#[lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_impl_for` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:52:6
+   |
+52 | impl<#[ty_impl_for] N> TrTy<N> for StTy<N> {
+   |      ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:57:9
+   |
+57 | fn f_lt<#[lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_fn` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:59:9
+   |
+59 | fn f_ty<#[ty_fn] O>(_: O) { }
+   |         ^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:63:13
+   |
+63 |     fn m_lt<#[lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `ty_meth` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:65:13
+   |
+65 |     fn m_ty<#[ty_meth] P>(_: P) { }
+   |             ^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: The attribute `lt_hof` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/feature-gate-custom_attribute2.rs:70:19
+   |
+70 |     where Q: for <#[lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+   |                   ^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/compile-fail/single-derive-attr.rs b/src/test/ui/feature-gate-custom_derive.rs
index cd37611aced..0b1b3141f5b 100644
--- a/src/test/compile-fail/single-derive-attr.rs
+++ b/src/test/ui/feature-gate-custom_derive.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-custom_derive
-
 #[derive_Clone]
 //~^ ERROR attributes of the form `#[derive_*]` are reserved
 struct Test;
diff --git a/src/test/ui/feature-gate-custom_derive.stderr b/src/test/ui/feature-gate-custom_derive.stderr
new file mode 100644
index 00000000000..e806c808631
--- /dev/null
+++ b/src/test/ui/feature-gate-custom_derive.stderr
@@ -0,0 +1,10 @@
+error: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644)
+  --> $DIR/feature-gate-custom_derive.rs:11:1
+   |
+11 | #[derive_Clone]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_derive)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-decl_macro.rs b/src/test/ui/feature-gate-decl_macro.rs
index c5c83977c77..c5c83977c77 100644
--- a/src/test/compile-fail/feature-gate-decl_macro.rs
+++ b/src/test/ui/feature-gate-decl_macro.rs
diff --git a/src/test/ui/feature-gate-decl_macro.stderr b/src/test/ui/feature-gate-decl_macro.stderr
new file mode 100644
index 00000000000..49ce4eb10b6
--- /dev/null
+++ b/src/test/ui/feature-gate-decl_macro.stderr
@@ -0,0 +1,10 @@
+error: `macro` is experimental (see issue #39412)
+  --> $DIR/feature-gate-decl_macro.rs:13:1
+   |
+13 | macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(decl_macro)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/type-parameter-invalid-lint.rs b/src/test/ui/feature-gate-default_type_parameter_fallback.rs
index f424cbf0c32..ccc5ec49f13 100644
--- a/src/test/compile-fail/type-parameter-invalid-lint.rs
+++ b/src/test/ui/feature-gate-default_type_parameter_fallback.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-default_type_parameter_fallback
-
 #![allow(unused)]
 
 fn avg<T=i32>(_: T) {}
diff --git a/src/test/ui/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gate-default_type_parameter_fallback.stderr
new file mode 100644
index 00000000000..d756a69e8c1
--- /dev/null
+++ b/src/test/ui/feature-gate-default_type_parameter_fallback.stderr
@@ -0,0 +1,21 @@
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+  --> $DIR/feature-gate-default_type_parameter_fallback.rs:13:8
+   |
+13 | fn avg<T=i32>(_: T) {}
+   |        ^
+   |
+   = note: #[deny(invalid_type_param_default)] on by default
+   = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions.
+  --> $DIR/feature-gate-default_type_parameter_fallback.rs:18:6
+   |
+18 | impl<T=i32> S<T> {}
+   |      ^
+   |
+   = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-doc_cfg.rs b/src/test/ui/feature-gate-doc_cfg.rs
index 1a77d918014..1a77d918014 100644
--- a/src/test/compile-fail/feature-gate-doc_cfg.rs
+++ b/src/test/ui/feature-gate-doc_cfg.rs
diff --git a/src/test/ui/feature-gate-doc_cfg.stderr b/src/test/ui/feature-gate-doc_cfg.stderr
new file mode 100644
index 00000000000..c2d8a934ab8
--- /dev/null
+++ b/src/test/ui/feature-gate-doc_cfg.stderr
@@ -0,0 +1,10 @@
+error: #[doc(cfg(...))] is experimental (see issue #43781)
+  --> $DIR/feature-gate-doc_cfg.rs:11:1
+   |
+11 | #[doc(cfg(unix))] //~ ERROR: #[doc(cfg(...))] is experimental
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-doc_masked.rs b/src/test/ui/feature-gate-doc_masked.rs
index bb5be9d6971..bb5be9d6971 100644
--- a/src/test/compile-fail/feature-gate-doc_masked.rs
+++ b/src/test/ui/feature-gate-doc_masked.rs
diff --git a/src/test/ui/feature-gate-doc_masked.stderr b/src/test/ui/feature-gate-doc_masked.stderr
new file mode 100644
index 00000000000..11020765304
--- /dev/null
+++ b/src/test/ui/feature-gate-doc_masked.stderr
@@ -0,0 +1,10 @@
+error: #[doc(masked)] is experimental (see issue #44027)
+  --> $DIR/feature-gate-doc_masked.rs:11:1
+   |
+11 | #[doc(masked)] //~ ERROR: #[doc(masked)] is experimental
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_masked)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gate-doc_spotlight.rs
index 6369358538d..6369358538d 100644
--- a/src/test/compile-fail/feature-gate-doc_spotlight.rs
+++ b/src/test/ui/feature-gate-doc_spotlight.rs
diff --git a/src/test/ui/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gate-doc_spotlight.stderr
new file mode 100644
index 00000000000..b743a1e94bc
--- /dev/null
+++ b/src/test/ui/feature-gate-doc_spotlight.stderr
@@ -0,0 +1,10 @@
+error: #[doc(spotlight)] is experimental (see issue #45040)
+  --> $DIR/feature-gate-doc_spotlight.rs:11:1
+   |
+11 | #[doc(spotlight)] //~ ERROR: #[doc(spotlight)] is experimental
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_spotlight)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs b/src/test/ui/feature-gate-dotdoteq_in_patterns.rs
index 1fb139bf07f..1fb139bf07f 100644
--- a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs
+++ b/src/test/ui/feature-gate-dotdoteq_in_patterns.rs
diff --git a/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr
new file mode 100644
index 00000000000..5319dcef2d5
--- /dev/null
+++ b/src/test/ui/feature-gate-dotdoteq_in_patterns.stderr
@@ -0,0 +1,10 @@
+error: `..=` syntax in patterns is experimental (see issue #28237)
+  --> $DIR/feature-gate-dotdoteq_in_patterns.rs:13:9
+   |
+13 |         0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental
+   |         ^^^^^^^
+   |
+   = help: add #![feature(dotdoteq_in_patterns)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs b/src/test/ui/feature-gate-dropck-ugeh-2.rs
index 70ec561439c..70ec561439c 100644
--- a/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs
+++ b/src/test/ui/feature-gate-dropck-ugeh-2.rs
diff --git a/src/test/ui/feature-gate-dropck-ugeh-2.stderr b/src/test/ui/feature-gate-dropck-ugeh-2.stderr
new file mode 100644
index 00000000000..0555b485d4c
--- /dev/null
+++ b/src/test/ui/feature-gate-dropck-ugeh-2.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated attribute `dropck_parametricity`: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future. See https://github.com/rust-lang/rust/issues/34761
+  --> $DIR/feature-gate-dropck-ugeh-2.rs:17:5
+   |
+17 |     #[unsafe_destructor_blind_to_params]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-dropck-ugeh-2.rs:11:9
+   |
+11 | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/ui/feature-gate-dropck-ugeh.rs
index 360895d30b0..360895d30b0 100644
--- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs
+++ b/src/test/ui/feature-gate-dropck-ugeh.rs
diff --git a/src/test/ui/feature-gate-dropck-ugeh.stderr b/src/test/ui/feature-gate-dropck-ugeh.stderr
new file mode 100644
index 00000000000..b030ebcd881
--- /dev/null
+++ b/src/test/ui/feature-gate-dropck-ugeh.stderr
@@ -0,0 +1,10 @@
+error: unsafe_destructor_blind_to_params has been replaced by may_dangle and will be removed in the future (see issue #28498)
+  --> $DIR/feature-gate-dropck-ugeh.rs:29:5
+   |
+29 |     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(dropck_parametricity)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-dyn-trait.rs b/src/test/ui/feature-gate-dyn-trait.rs
index 4b3803d019b..4b3803d019b 100644
--- a/src/test/compile-fail/feature-gate-dyn-trait.rs
+++ b/src/test/ui/feature-gate-dyn-trait.rs
diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr
new file mode 100644
index 00000000000..28ecfdf1131
--- /dev/null
+++ b/src/test/ui/feature-gate-dyn-trait.stderr
@@ -0,0 +1,10 @@
+error: `dyn Trait` syntax is unstable (see issue #44662)
+  --> $DIR/feature-gate-dyn-trait.rs:12:14
+   |
+12 | type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
+   |              ^^^^^^^^^
+   |
+   = help: add #![feature(dyn_trait)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-exclusive-range-pattern.rs b/src/test/ui/feature-gate-exclusive-range-pattern.rs
index e0b6d5986ff..e0b6d5986ff 100644
--- a/src/test/compile-fail/feature-gate-exclusive-range-pattern.rs
+++ b/src/test/ui/feature-gate-exclusive-range-pattern.rs
diff --git a/src/test/ui/feature-gate-exclusive-range-pattern.stderr b/src/test/ui/feature-gate-exclusive-range-pattern.stderr
new file mode 100644
index 00000000000..c6785d6f29d
--- /dev/null
+++ b/src/test/ui/feature-gate-exclusive-range-pattern.stderr
@@ -0,0 +1,10 @@
+error: exclusive range pattern syntax is experimental (see issue #37854)
+  --> $DIR/feature-gate-exclusive-range-pattern.rs:13:9
+   |
+13 |         0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
+   |         ^^^^^^
+   |
+   = help: add #![feature(exclusive_range_pattern)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-extern_types.rs b/src/test/ui/feature-gate-extern_types.rs
index 1203b598df3..1203b598df3 100644
--- a/src/test/compile-fail/feature-gate-extern_types.rs
+++ b/src/test/ui/feature-gate-extern_types.rs
diff --git a/src/test/ui/feature-gate-extern_types.stderr b/src/test/ui/feature-gate-extern_types.stderr
new file mode 100644
index 00000000000..3815862e899
--- /dev/null
+++ b/src/test/ui/feature-gate-extern_types.stderr
@@ -0,0 +1,10 @@
+error: extern types are experimental (see issue #43467)
+  --> $DIR/feature-gate-extern_types.rs:12:5
+   |
+12 |     type T; //~ ERROR extern types are experimental
+   |     ^^^^^^^
+   |
+   = help: add #![feature(extern_types)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-external_doc.rs b/src/test/ui/feature-gate-external_doc.rs
index fa0a2a29078..fa0a2a29078 100644
--- a/src/test/compile-fail/feature-gate-external_doc.rs
+++ b/src/test/ui/feature-gate-external_doc.rs
diff --git a/src/test/ui/feature-gate-external_doc.stderr b/src/test/ui/feature-gate-external_doc.stderr
new file mode 100644
index 00000000000..5479ab8bc91
--- /dev/null
+++ b/src/test/ui/feature-gate-external_doc.stderr
@@ -0,0 +1,10 @@
+error: #[doc(include = "...")] is experimental (see issue #44732)
+  --> $DIR/feature-gate-external_doc.rs:11:1
+   |
+11 | #[doc(include="asdf.md")] //~ ERROR: #[doc(include = "...")] is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(external_doc)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-feature-gate.rs b/src/test/ui/feature-gate-feature-gate.rs
index b903b29658b..b903b29658b 100644
--- a/src/test/compile-fail/feature-gate-feature-gate.rs
+++ b/src/test/ui/feature-gate-feature-gate.rs
diff --git a/src/test/ui/feature-gate-feature-gate.stderr b/src/test/ui/feature-gate-feature-gate.stderr
new file mode 100644
index 00000000000..3d5f0d70bb2
--- /dev/null
+++ b/src/test/ui/feature-gate-feature-gate.stderr
@@ -0,0 +1,14 @@
+error: unstable feature
+  --> $DIR/feature-gate-feature-gate.rs:12:12
+   |
+12 | #![feature(intrinsics)] //~ ERROR unstable feature
+   |            ^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-feature-gate.rs:11:11
+   |
+11 | #![forbid(unstable_features)]
+   |           ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-fn_must_use-cap-lints-allow.rs b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs
index 1c04199c05f..1c04199c05f 100644
--- a/src/test/compile-fail/feature-gate-fn_must_use-cap-lints-allow.rs
+++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs
diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
new file mode 100644
index 00000000000..9b16e9be68a
--- /dev/null
+++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
@@ -0,0 +1,6 @@
+error: compilation successful
+  --> $DIR/feature-gate-fn_must_use-cap-lints-allow.rs:22:1
+   |
+22 | fn main() {} //~ ERROR compilation successful
+   | ^^^^^^^^^^^^
+
diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/ui/feature-gate-fn_must_use.rs
index 72fdcc76cf4..72fdcc76cf4 100644
--- a/src/test/compile-fail/feature-gate-fn_must_use.rs
+++ b/src/test/ui/feature-gate-fn_must_use.rs
diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr
new file mode 100644
index 00000000000..ed4953d27b8
--- /dev/null
+++ b/src/test/ui/feature-gate-fn_must_use.stderr
@@ -0,0 +1,22 @@
+warning: `#[must_use]` on methods is experimental (see issue #43302)
+  --> $DIR/feature-gate-fn_must_use.rs:16:5
+   |
+16 |     #[must_use] //~ WARN `#[must_use]` on methods is experimental
+   |     ^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_must_use)] to the crate attributes to enable
+
+warning: `#[must_use]` on functions is experimental (see issue #43302)
+  --> $DIR/feature-gate-fn_must_use.rs:20:1
+   |
+20 | #[must_use] //~ WARN `#[must_use]` on functions is experimental
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_must_use)] to the crate attributes to enable
+
+error: compilation successful
+  --> $DIR/feature-gate-fn_must_use.rs:31:1
+   |
+31 | fn main() {} //~ ERROR compilation successful
+   | ^^^^^^^^^^^^
+
diff --git a/src/test/compile-fail/feature-gate-fundamental.rs b/src/test/ui/feature-gate-fundamental.rs
index 18718a0d0be..18718a0d0be 100644
--- a/src/test/compile-fail/feature-gate-fundamental.rs
+++ b/src/test/ui/feature-gate-fundamental.rs
diff --git a/src/test/ui/feature-gate-fundamental.stderr b/src/test/ui/feature-gate-fundamental.stderr
new file mode 100644
index 00000000000..0fc75ee30b9
--- /dev/null
+++ b/src/test/ui/feature-gate-fundamental.stderr
@@ -0,0 +1,10 @@
+error: the `#[fundamental]` attribute is an experimental feature (see issue #29635)
+  --> $DIR/feature-gate-fundamental.rs:11:1
+   |
+11 | #[fundamental] //~ ERROR the `#[fundamental]` attribute is an experimental feature
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fundamental)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-generators.rs b/src/test/ui/feature-gate-generators.rs
index 3754f92d8cd..3754f92d8cd 100644
--- a/src/test/compile-fail/feature-gate-generators.rs
+++ b/src/test/ui/feature-gate-generators.rs
diff --git a/src/test/ui/feature-gate-generators.stderr b/src/test/ui/feature-gate-generators.stderr
new file mode 100644
index 00000000000..82acb401338
--- /dev/null
+++ b/src/test/ui/feature-gate-generators.stderr
@@ -0,0 +1,10 @@
+error: yield syntax is experimental
+  --> $DIR/feature-gate-generators.rs:12:5
+   |
+12 |     yield true; //~ ERROR yield syntax is experimental
+   |     ^^^^^^^^^^
+   |
+   = help: add #![feature(generators)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-generic_associated_types.rs b/src/test/ui/feature-gate-generic_associated_types.rs
index 724ec2496f2..724ec2496f2 100644
--- a/src/test/compile-fail/feature-gate-generic_associated_types.rs
+++ b/src/test/ui/feature-gate-generic_associated_types.rs
diff --git a/src/test/ui/feature-gate-generic_associated_types.stderr b/src/test/ui/feature-gate-generic_associated_types.stderr
new file mode 100644
index 00000000000..7b2507e1fb1
--- /dev/null
+++ b/src/test/ui/feature-gate-generic_associated_types.stderr
@@ -0,0 +1,34 @@
+error: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:14:5
+   |
+14 |     type Pointer<T>: Deref<Target = T>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+   |
+16 |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:22:5
+   |
+22 |     type Pointer<usize> = Box<usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: generic associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:24:5
+   |
+24 |     type Pointer2<u32> = Box<u32>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs b/src/test/ui/feature-gate-generic_param_attrs.rs
index b341f7c7825..944802f450a 100644
--- a/src/test/compile-fail/attr-on-generic-formals-wo-feature-gate.rs
+++ b/src/test/ui/feature-gate-generic_param_attrs.rs
@@ -16,8 +16,6 @@
 // using `rustc_attrs` feature. There is a separate compile-fail/ test
 // ensuring that the attribute feature-gating works in this context.)
 
-// gate-test-generic_param_attrs
-
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
diff --git a/src/test/ui/feature-gate-generic_param_attrs.stderr b/src/test/ui/feature-gate-generic_param_attrs.stderr
new file mode 100644
index 00000000000..da2e6403029
--- /dev/null
+++ b/src/test/ui/feature-gate-generic_param_attrs.stderr
@@ -0,0 +1,138 @@
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:22:13
+   |
+22 | struct StLt<#[rustc_lt_struct] 'a>(&'a u32);
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:24:13
+   |
+24 | struct StTy<#[rustc_ty_struct] I>(I);
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:27:11
+   |
+27 | enum EnLt<#[rustc_lt_enum] 'b> { A(&'b u32), B }
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:29:11
+   |
+29 | enum EnTy<#[rustc_ty_enum] J> { A(J), B }
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:32:12
+   |
+32 | trait TrLt<#[rustc_lt_trait] 'c> { fn foo(&self, _: &'c [u32]) -> &'c u32; }
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:34:12
+   |
+34 | trait TrTy<#[rustc_ty_trait] K> { fn foo(&self, _: K); }
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:37:11
+   |
+37 | type TyLt<#[rustc_lt_type] 'd> = &'d u32;
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:39:11
+   |
+39 | type TyTy<#[rustc_ty_type] L> = (L, );
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:42:6
+   |
+42 | impl<#[rustc_lt_inherent] 'e> StLt<'e> { }
+   |      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:44:6
+   |
+44 | impl<#[rustc_ty_inherent] M> StTy<M> { }
+   |      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:47:6
+   |
+47 | impl<#[rustc_lt_impl_for] 'f> TrLt<'f> for StLt<'f> {
+   |      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:51:6
+   |
+51 | impl<#[rustc_ty_impl_for] N> TrTy<N> for StTy<N> {
+   |      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:56:9
+   |
+56 | fn f_lt<#[rustc_lt_fn] 'g>(_: &'g [u32]) -> &'g u32 { loop { } }
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:58:9
+   |
+58 | fn f_ty<#[rustc_ty_fn] O>(_: O) { }
+   |         ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:62:13
+   |
+62 |     fn m_lt<#[rustc_lt_meth] 'h>(_: &'h [u32]) -> &'h u32 { loop { } }
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on type parameter bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:64:13
+   |
+64 |     fn m_ty<#[rustc_ty_meth] P>(_: P) { }
+   |             ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: attributes on lifetime bindings are experimental (see issue #34761)
+  --> $DIR/feature-gate-generic_param_attrs.rs:69:19
+   |
+69 |     where Q: for <#[rustc_lt_hof] 'i> Fn(&'i [u32]) -> &'i u32
+   |                   ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_param_attrs)] to the crate attributes to enable
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-global_allocator.rs b/src/test/ui/feature-gate-global_allocator.rs
index ff3c342f9e0..ff3c342f9e0 100644
--- a/src/test/compile-fail/feature-gate-global_allocator.rs
+++ b/src/test/ui/feature-gate-global_allocator.rs
diff --git a/src/test/ui/feature-gate-global_allocator.stderr b/src/test/ui/feature-gate-global_allocator.stderr
new file mode 100644
index 00000000000..7e6c4288ff3
--- /dev/null
+++ b/src/test/ui/feature-gate-global_allocator.stderr
@@ -0,0 +1,10 @@
+error: the `#[global_allocator]` attribute is an experimental feature
+  --> $DIR/feature-gate-global_allocator.rs:11:1
+   |
+11 | #[global_allocator] //~ ERROR: attribute is an experimental feature
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(global_allocator)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-global_asm.rs b/src/test/ui/feature-gate-global_asm.rs
index 77f61ba47b0..77f61ba47b0 100644
--- a/src/test/compile-fail/feature-gate-global_asm.rs
+++ b/src/test/ui/feature-gate-global_asm.rs
diff --git a/src/test/ui/feature-gate-global_asm.stderr b/src/test/ui/feature-gate-global_asm.stderr
new file mode 100644
index 00000000000..de0ba1a7b32
--- /dev/null
+++ b/src/test/ui/feature-gate-global_asm.stderr
@@ -0,0 +1,10 @@
+error: `global_asm!` is not stable enough for use and is subject to change (see issue #35119)
+  --> $DIR/feature-gate-global_asm.rs:11:1
+   |
+11 | global_asm!(""); //~ ERROR `global_asm!` is not stable
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(global_asm)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/i128-feature.rs b/src/test/ui/feature-gate-i128_type.rs
index e94fd14a421..ddb49a3e5d9 100644
--- a/src/test/compile-fail/i128-feature.rs
+++ b/src/test/ui/feature-gate-i128_type.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-i128_type
-
 fn test2() {
     0i128; //~ ERROR 128-bit integers are not stable
 }
diff --git a/src/test/ui/feature-gate-i128_type.stderr b/src/test/ui/feature-gate-i128_type.stderr
new file mode 100644
index 00000000000..df623cac49a
--- /dev/null
+++ b/src/test/ui/feature-gate-i128_type.stderr
@@ -0,0 +1,18 @@
+error: 128-bit integers are not stable (see issue #35118)
+  --> $DIR/feature-gate-i128_type.rs:12:5
+   |
+12 |     0i128; //~ ERROR 128-bit integers are not stable
+   |     ^^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error: 128-bit integers are not stable (see issue #35118)
+  --> $DIR/feature-gate-i128_type.rs:16:5
+   |
+16 |     0u128; //~ ERROR 128-bit integers are not stable
+   |     ^^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/i128-feature-2.rs b/src/test/ui/feature-gate-i128_type2.rs
index d3bd810ceb2..d3bd810ceb2 100644
--- a/src/test/compile-fail/i128-feature-2.rs
+++ b/src/test/ui/feature-gate-i128_type2.rs
diff --git a/src/test/ui/feature-gate-i128_type2.stderr b/src/test/ui/feature-gate-i128_type2.stderr
new file mode 100644
index 00000000000..26653a5739b
--- /dev/null
+++ b/src/test/ui/feature-gate-i128_type2.stderr
@@ -0,0 +1,46 @@
+error: 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-i128_type2.rs:13:15
+   |
+13 | fn test1() -> i128 { //~ ERROR 128-bit type is unstable
+   |               ^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error: 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-i128_type2.rs:17:17
+   |
+17 | fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable
+   |                 ^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error: 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-i128_type2.rs:22:12
+   |
+22 |     let x: i128 = 0; //~ ERROR 128-bit type is unstable
+   |            ^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error: 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-i128_type2.rs:26:12
+   |
+26 |     let x: u128 = 0; //~ ERROR 128-bit type is unstable
+   |            ^^^^
+   |
+   = help: add #![feature(i128_type)] to the crate attributes to enable
+
+error[E0601]: main function not found
+
+error: repr with 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-i128_type2.rs:30:1
+   |
+30 | / enum A { //~ ERROR 128-bit type is unstable
+31 | |     A(u64)
+32 | | }
+   | |_^
+   |
+   = help: add #![feature(repr128)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-in_band_lifetimes.rs b/src/test/ui/feature-gate-in_band_lifetimes.rs
index ae1f81c2f57..ae1f81c2f57 100644
--- a/src/test/compile-fail/feature-gate-in_band_lifetimes.rs
+++ b/src/test/ui/feature-gate-in_band_lifetimes.rs
diff --git a/src/test/ui/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gate-in_band_lifetimes.stderr
new file mode 100644
index 00000000000..3b03ef2dd33
--- /dev/null
+++ b/src/test/ui/feature-gate-in_band_lifetimes.stderr
@@ -0,0 +1,104 @@
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:13:12
+   |
+13 | fn foo(x: &'x u8) -> &'x u8 { x }
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:13:23
+   |
+13 | fn foo(x: &'x u8) -> &'x u8 { x }
+   |                       ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:25:12
+   |
+25 | impl<'a> X<'b> {
+   |            ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:27:27
+   |
+27 |     fn inner_2(&self) -> &'b u8 {
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:33:8
+   |
+33 | impl X<'b> {
+   |        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:35:27
+   |
+35 |     fn inner_3(&self) -> &'b u8 {
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:43:9
+   |
+43 | impl Y<&'a u8> {
+   |         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:45:25
+   |
+45 |     fn inner(&self) -> &'a u8 {
+   |                         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:53:27
+   |
+53 |     fn any_lifetime() -> &'b u8;
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:55:27
+   |
+55 |     fn borrowed_lifetime(&'b self) -> &'b u8;
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:55:40
+   |
+55 |     fn borrowed_lifetime(&'b self) -> &'b u8;
+   |                                        ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:60:14
+   |
+60 | impl MyTrait<'a> for Y<&'a u8> {
+   |              ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:60:25
+   |
+60 | impl MyTrait<'a> for Y<&'a u8> {
+   |                         ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:63:31
+   |
+63 |     fn my_lifetime(&self) -> &'a u8 { self.0 }
+   |                               ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:65:27
+   |
+65 |     fn any_lifetime() -> &'b u8 { &0 }
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:67:27
+   |
+67 |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                           ^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/feature-gate-in_band_lifetimes.rs:67:40
+   |
+67 |     fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+   |                                        ^^ undeclared lifetime
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-intrinsics.rs b/src/test/ui/feature-gate-intrinsics.rs
index a4c09b21c90..a4c09b21c90 100644
--- a/src/test/compile-fail/feature-gate-intrinsics.rs
+++ b/src/test/ui/feature-gate-intrinsics.rs
diff --git a/src/test/ui/feature-gate-intrinsics.stderr b/src/test/ui/feature-gate-intrinsics.stderr
new file mode 100644
index 00000000000..5382122e30e
--- /dev/null
+++ b/src/test/ui/feature-gate-intrinsics.stderr
@@ -0,0 +1,21 @@
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-intrinsics.rs:11:1
+   |
+11 | / extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
+12 | |     fn bar();
+13 | | }
+   | |_^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: intrinsics are subject to change
+  --> $DIR/feature-gate-intrinsics.rs:15:1
+   |
+15 | / extern "rust-intrinsic" fn baz() {  //~ ERROR intrinsics are subject to change
+16 | | }
+   | |_^
+   |
+   = help: add #![feature(intrinsics)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-lang-items.rs b/src/test/ui/feature-gate-lang-items.rs
index 0435ff4c332..0435ff4c332 100644
--- a/src/test/compile-fail/feature-gate-lang-items.rs
+++ b/src/test/ui/feature-gate-lang-items.rs
diff --git a/src/test/ui/feature-gate-lang-items.stderr b/src/test/ui/feature-gate-lang-items.stderr
new file mode 100644
index 00000000000..dab8ce23192
--- /dev/null
+++ b/src/test/ui/feature-gate-lang-items.stderr
@@ -0,0 +1,10 @@
+error: language items are subject to change
+  --> $DIR/feature-gate-lang-items.rs:11:1
+   |
+11 | #[lang="foo"]   //~ ERROR language items are subject to change
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(lang_items)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-link-args.rs b/src/test/ui/feature-gate-link_args.rs
index 82f5db3042b..bd48ac673dd 100644
--- a/src/test/compile-fail/gated-link-args.rs
+++ b/src/test/ui/feature-gate-link_args.rs
@@ -12,8 +12,6 @@
 // feature gate, both when it occurs where expected (atop
 // `extern { }` blocks) and where unexpected.
 
-// gate-test-link_args
-
 // sidestep warning (which is correct, but misleading for
 // purposes of this test)
 #![allow(unused_attributes)]
diff --git a/src/test/ui/feature-gate-link_args.stderr b/src/test/ui/feature-gate-link_args.stderr
new file mode 100644
index 00000000000..d6d059007d1
--- /dev/null
+++ b/src/test/ui/feature-gate-link_args.stderr
@@ -0,0 +1,26 @@
+error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:22:1
+   |
+22 | #[link_args = "-l expected_use_case"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:26:1
+   |
+26 | #[link_args = "-l unexected_use_on_non_extern_item"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error: the `link_args` attribute is experimental and not portable across platforms, it is recommended to use `#[link(name = "foo")] instead (see issue #29596)
+  --> $DIR/feature-gate-link_args.rs:19:1
+   |
+19 | #![link_args = "-l unexpected_use_as_inner_attr_on_mod"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_args)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/link-cfg-gated.rs b/src/test/ui/feature-gate-link_cfg.rs
index bb6fb9e3563..27918a27caf 100644
--- a/src/test/compile-fail/link-cfg-gated.rs
+++ b/src/test/ui/feature-gate-link_cfg.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-link_cfg
-
 #[link(name = "foo", cfg(foo))]
 //~^ ERROR: is feature gated
 extern {}
diff --git a/src/test/ui/feature-gate-link_cfg.stderr b/src/test/ui/feature-gate-link_cfg.stderr
new file mode 100644
index 00000000000..bbc52bd9d20
--- /dev/null
+++ b/src/test/ui/feature-gate-link_cfg.stderr
@@ -0,0 +1,10 @@
+error: is feature gated (see issue #37406)
+  --> $DIR/feature-gate-link_cfg.rs:11:1
+   |
+11 | #[link(name = "foo", cfg(foo))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_cfg)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-link-llvm-intrinsics.rs b/src/test/ui/feature-gate-link_llvm_intrinsics.rs
index 681824ae71d..92a1b071437 100644
--- a/src/test/compile-fail/gated-link-llvm-intrinsics.rs
+++ b/src/test/ui/feature-gate-link_llvm_intrinsics.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-link_llvm_intrinsics
-
 extern {
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
diff --git a/src/test/ui/feature-gate-link_llvm_intrinsics.stderr b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr
new file mode 100644
index 00000000000..b2e2caaa51a
--- /dev/null
+++ b/src/test/ui/feature-gate-link_llvm_intrinsics.stderr
@@ -0,0 +1,10 @@
+error: linking to LLVM intrinsics is experimental (see issue #29602)
+  --> $DIR/feature-gate-link_llvm_intrinsics.rs:13:5
+   |
+13 |     fn sqrt(x: f32) -> f32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(link_llvm_intrinsics)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/linkage1.rs b/src/test/ui/feature-gate-linkage.rs
index 1cf208f0215..555cc2b9a7a 100644
--- a/src/test/compile-fail/linkage1.rs
+++ b/src/test/ui/feature-gate-linkage.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-linkage
-
 extern {
     #[linkage = "extern_weak"] static foo: isize;
     //~^ ERROR: the `linkage` attribute is experimental and not portable
diff --git a/src/test/ui/feature-gate-linkage.stderr b/src/test/ui/feature-gate-linkage.stderr
new file mode 100644
index 00000000000..62d857ddf2c
--- /dev/null
+++ b/src/test/ui/feature-gate-linkage.stderr
@@ -0,0 +1,10 @@
+error: the `linkage` attribute is experimental and not portable across platforms (see issue #29603)
+  --> $DIR/feature-gate-linkage.rs:12:5
+   |
+12 |     #[linkage = "extern_weak"] static foo: isize;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(linkage)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-linker-flavor.rs b/src/test/ui/feature-gate-linker-flavor.rs
index 955ec39cda1..955ec39cda1 100644
--- a/src/test/compile-fail/feature-gate-linker-flavor.rs
+++ b/src/test/ui/feature-gate-linker-flavor.rs
diff --git a/src/test/ui/feature-gate-linker-flavor.stderr b/src/test/ui/feature-gate-linker-flavor.stderr
new file mode 100644
index 00000000000..383e75e3d17
--- /dev/null
+++ b/src/test/ui/feature-gate-linker-flavor.stderr
@@ -0,0 +1,10 @@
+error: the `#[used]` attribute is an experimental feature (see issue #40289)
+  --> $DIR/feature-gate-linker-flavor.rs:16:1
+   |
+16 | #[used]
+   | ^^^^^^^
+   |
+   = help: add #![feature(used)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/log-syntax-gate.rs b/src/test/ui/feature-gate-log_syntax.rs
index b9688af35dc..63c66e53c5e 100644
--- a/src/test/compile-fail/log-syntax-gate.rs
+++ b/src/test/ui/feature-gate-log_syntax.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-log_syntax
-
 fn main() {
     log_syntax!() //~ ERROR `log_syntax!` is not stable enough
 }
diff --git a/src/test/ui/feature-gate-log_syntax.stderr b/src/test/ui/feature-gate-log_syntax.stderr
new file mode 100644
index 00000000000..f1c0d305f6c
--- /dev/null
+++ b/src/test/ui/feature-gate-log_syntax.stderr
@@ -0,0 +1,10 @@
+error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-log_syntax.rs:12:5
+   |
+12 |     log_syntax!() //~ ERROR `log_syntax!` is not stable enough
+   |     ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(log_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/log-syntax-gate2.rs b/src/test/ui/feature-gate-log_syntax2.rs
index dcbe7eefee5..dcbe7eefee5 100644
--- a/src/test/compile-fail/log-syntax-gate2.rs
+++ b/src/test/ui/feature-gate-log_syntax2.rs
diff --git a/src/test/ui/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gate-log_syntax2.stderr
new file mode 100644
index 00000000000..b1bb5557eed
--- /dev/null
+++ b/src/test/ui/feature-gate-log_syntax2.stderr
@@ -0,0 +1,10 @@
+error: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-log_syntax2.rs:14:20
+   |
+14 |     println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable
+   |                    ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(log_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-macro-vis-matcher.rs b/src/test/ui/feature-gate-macro-vis-matcher.rs
index 5d6f2acea83..5d6f2acea83 100644
--- a/src/test/compile-fail/feature-gate-macro-vis-matcher.rs
+++ b/src/test/ui/feature-gate-macro-vis-matcher.rs
diff --git a/src/test/ui/feature-gate-macro-vis-matcher.stderr b/src/test/ui/feature-gate-macro-vis-matcher.stderr
new file mode 100644
index 00000000000..09db5009165
--- /dev/null
+++ b/src/test/ui/feature-gate-macro-vis-matcher.stderr
@@ -0,0 +1,10 @@
+error: :vis fragment specifier is experimental and subject to change (see issue #41022)
+  --> $DIR/feature-gate-macro-vis-matcher.rs:14:19
+   |
+14 | macro_rules! m { ($v:vis) => {} }
+   |                   ^^^^^^
+   |
+   = help: add #![feature(macro_vis_matcher)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-main.rs b/src/test/ui/feature-gate-main.rs
index db1c1a94417..db1c1a94417 100644
--- a/src/test/compile-fail/feature-gate-main.rs
+++ b/src/test/ui/feature-gate-main.rs
diff --git a/src/test/ui/feature-gate-main.stderr b/src/test/ui/feature-gate-main.stderr
new file mode 100644
index 00000000000..90cf12822c8
--- /dev/null
+++ b/src/test/ui/feature-gate-main.stderr
@@ -0,0 +1,10 @@
+error: declaration of a nonstandard #[main] function may change over time, for now a top-level `fn main()` is required (see issue #29634)
+  --> $DIR/feature-gate-main.rs:12:1
+   |
+12 | fn foo() {} //~ ERROR: declaration of a nonstandard #[main] function may change over time
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(main)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-match_beginning_vert.rs b/src/test/ui/feature-gate-match_beginning_vert.rs
index 9085563c99d..9085563c99d 100644
--- a/src/test/compile-fail/feature-gate-match_beginning_vert.rs
+++ b/src/test/ui/feature-gate-match_beginning_vert.rs
diff --git a/src/test/ui/feature-gate-match_beginning_vert.stderr b/src/test/ui/feature-gate-match_beginning_vert.stderr
new file mode 100644
index 00000000000..88053adfafa
--- /dev/null
+++ b/src/test/ui/feature-gate-match_beginning_vert.stderr
@@ -0,0 +1,26 @@
+error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+  --> $DIR/feature-gate-match_beginning_vert.rs:24:9
+   |
+24 |         | A => println!("A"),
+   |         ^
+   |
+   = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
+
+error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+  --> $DIR/feature-gate-match_beginning_vert.rs:26:9
+   |
+26 |         | B | C => println!("BC!"),
+   |         ^
+   |
+   = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
+
+error: Use of a '|' at the beginning of a match arm is experimental (see issue #44101)
+  --> $DIR/feature-gate-match_beginning_vert.rs:28:9
+   |
+28 |         | _ => {},
+   |         ^
+   |
+   = help: add #![feature(match_beginning_vert)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-match_default_bindings.rs b/src/test/ui/feature-gate-match_default_bindings.rs
index 4ee2c1e2936..4ee2c1e2936 100644
--- a/src/test/compile-fail/feature-gate-match_default_bindings.rs
+++ b/src/test/ui/feature-gate-match_default_bindings.rs
diff --git a/src/test/ui/feature-gate-match_default_bindings.stderr b/src/test/ui/feature-gate-match_default_bindings.stderr
new file mode 100644
index 00000000000..d86e8248f08
--- /dev/null
+++ b/src/test/ui/feature-gate-match_default_bindings.stderr
@@ -0,0 +1,10 @@
+error: non-reference pattern used to match a reference (see issue #42640)
+  --> $DIR/feature-gate-match_default_bindings.rs:13:9
+   |
+13 |         Some(n) => {},
+   |         ^^^^^^^ help: consider using a reference: `&Some(n)`
+   |
+   = help: add #![feature(match_default_bindings)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-may-dangle.rs b/src/test/ui/feature-gate-may-dangle.rs
index 0bf1e93d9aa..0bf1e93d9aa 100644
--- a/src/test/compile-fail/feature-gate-may-dangle.rs
+++ b/src/test/ui/feature-gate-may-dangle.rs
diff --git a/src/test/ui/feature-gate-may-dangle.stderr b/src/test/ui/feature-gate-may-dangle.stderr
new file mode 100644
index 00000000000..e51723d058e
--- /dev/null
+++ b/src/test/ui/feature-gate-may-dangle.stderr
@@ -0,0 +1,10 @@
+error: may_dangle has unstable semantics and may be removed in the future (see issue #34761)
+  --> $DIR/feature-gate-may-dangle.rs:18:6
+   |
+18 | impl<#[may_dangle] A> Drop for Pt<A> {
+   |      ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(dropck_eyepatch)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-naked_functions.rs b/src/test/ui/feature-gate-naked_functions.rs
index 5eb41181027..ceb475e1192 100644
--- a/src/test/compile-fail/gated-naked_functions.rs
+++ b/src/test/ui/feature-gate-naked_functions.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-naked_functions
-
 #[naked]
 //~^ the `#[naked]` attribute is an experimental feature
 fn naked() {}
diff --git a/src/test/ui/feature-gate-naked_functions.stderr b/src/test/ui/feature-gate-naked_functions.stderr
new file mode 100644
index 00000000000..9655982574c
--- /dev/null
+++ b/src/test/ui/feature-gate-naked_functions.stderr
@@ -0,0 +1,18 @@
+error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+  --> $DIR/feature-gate-naked_functions.rs:11:1
+   |
+11 | #[naked]
+   | ^^^^^^^^
+   |
+   = help: add #![feature(naked_functions)] to the crate attributes to enable
+
+error: the `#[naked]` attribute is an experimental feature (see issue #32408)
+  --> $DIR/feature-gate-naked_functions.rs:15:1
+   |
+15 | #[naked]
+   | ^^^^^^^^
+   |
+   = help: add #![feature(naked_functions)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-needs-allocator.rs b/src/test/ui/feature-gate-needs-allocator.rs
index 1809564f5de..1809564f5de 100644
--- a/src/test/compile-fail/feature-gate-needs-allocator.rs
+++ b/src/test/ui/feature-gate-needs-allocator.rs
diff --git a/src/test/ui/feature-gate-needs-allocator.stderr b/src/test/ui/feature-gate-needs-allocator.stderr
new file mode 100644
index 00000000000..5124c10cb47
--- /dev/null
+++ b/src/test/ui/feature-gate-needs-allocator.stderr
@@ -0,0 +1,10 @@
+error: the `#[needs_allocator]` attribute is an experimental feature
+  --> $DIR/feature-gate-needs-allocator.rs:11:1
+   |
+11 | #![needs_allocator] //~ ERROR the `#[needs_allocator]` attribute is
+   | ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(allocator_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/ui/feature-gate-negate-unsigned.rs
index 599e31341f2..599e31341f2 100644
--- a/src/test/compile-fail/feature-gate-negate-unsigned.rs
+++ b/src/test/ui/feature-gate-negate-unsigned.rs
diff --git a/src/test/ui/feature-gate-negate-unsigned.stderr b/src/test/ui/feature-gate-negate-unsigned.stderr
new file mode 100644
index 00000000000..d4311594517
--- /dev/null
+++ b/src/test/ui/feature-gate-negate-unsigned.stderr
@@ -0,0 +1,14 @@
+error[E0600]: cannot apply unary operator `-` to type `usize`
+  --> $DIR/feature-gate-negate-unsigned.rs:20:23
+   |
+20 |     let _max: usize = -1;
+   |                       ^^
+
+error[E0600]: cannot apply unary operator `-` to type `u8`
+  --> $DIR/feature-gate-negate-unsigned.rs:24:14
+   |
+24 |     let _y = -x;
+   |              ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/never-disabled.rs b/src/test/ui/feature-gate-never_type.rs
index fb6b34fcbb6..11b9f412957 100644
--- a/src/test/compile-fail/never-disabled.rs
+++ b/src/test/ui/feature-gate-never_type.rs
@@ -10,8 +10,6 @@
 
 // Test that ! errors when used in illegal positions with feature(never_type) disabled
 
-// gate-test-never_type
-
 trait Foo {
     type Wub;
 }
diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr
new file mode 100644
index 00000000000..c242e613ead
--- /dev/null
+++ b/src/test/ui/feature-gate-never_type.stderr
@@ -0,0 +1,42 @@
+error: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:17:17
+   |
+17 | type Ma = (u32, !, i32); //~ ERROR type is experimental
+   |                 ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:18:20
+   |
+18 | type Meeshka = Vec<!>; //~ ERROR type is experimental
+   |                    ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:19:16
+   |
+19 | type Mow = &fn(!) -> !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:20:19
+   |
+20 | type Skwoz = &mut !; //~ ERROR type is experimental
+   |                   ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:23:16
+   |
+23 |     type Wub = !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-no-debug-2.rs b/src/test/ui/feature-gate-no-debug-2.rs
index b663c136ee5..b663c136ee5 100644
--- a/src/test/compile-fail/feature-gate-no-debug-2.rs
+++ b/src/test/ui/feature-gate-no-debug-2.rs
diff --git a/src/test/ui/feature-gate-no-debug-2.stderr b/src/test/ui/feature-gate-no-debug-2.stderr
new file mode 100644
index 00000000000..231fc400115
--- /dev/null
+++ b/src/test/ui/feature-gate-no-debug-2.stderr
@@ -0,0 +1,14 @@
+error: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
+  --> $DIR/feature-gate-no-debug-2.rs:14:1
+   |
+14 | #[no_debug] //~ ERROR use of deprecated attribute `no_debug`
+   | ^^^^^^^^^^^ help: remove this attribute
+   |
+note: lint level defined here
+  --> $DIR/feature-gate-no-debug-2.rs:11:9
+   |
+11 | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-no-debug.rs b/src/test/ui/feature-gate-no-debug.rs
index d21493de50a..d21493de50a 100644
--- a/src/test/compile-fail/feature-gate-no-debug.rs
+++ b/src/test/ui/feature-gate-no-debug.rs
diff --git a/src/test/ui/feature-gate-no-debug.stderr b/src/test/ui/feature-gate-no-debug.stderr
new file mode 100644
index 00000000000..83a8189c095
--- /dev/null
+++ b/src/test/ui/feature-gate-no-debug.stderr
@@ -0,0 +1,10 @@
+error: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand (see issue #29721)
+  --> $DIR/feature-gate-no-debug.rs:13:1
+   |
+13 | #[no_debug] //~ ERROR the `#[no_debug]` attribute was
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(no_debug)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-no-core.rs b/src/test/ui/feature-gate-no_core.rs
index 66b9c2e5670..0a55a8a78ce 100644
--- a/src/test/compile-fail/gated-no-core.rs
+++ b/src/test/ui/feature-gate-no_core.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-no_core
-
 #![no_core] //~ ERROR no_core is experimental
 
 fn main() {}
diff --git a/src/test/ui/feature-gate-no_core.stderr b/src/test/ui/feature-gate-no_core.stderr
new file mode 100644
index 00000000000..02e0b176249
--- /dev/null
+++ b/src/test/ui/feature-gate-no_core.stderr
@@ -0,0 +1,10 @@
+error: no_core is experimental (see issue #29639)
+  --> $DIR/feature-gate-no_core.rs:11:1
+   |
+11 | #![no_core] //~ ERROR no_core is experimental
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(no_core)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-non-ascii-idents.rs b/src/test/ui/feature-gate-non_ascii_idents.rs
index 1dff22839ad..9e042c3a7d5 100644
--- a/src/test/compile-fail/gated-non-ascii-idents.rs
+++ b/src/test/ui/feature-gate-non_ascii_idents.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-non_ascii_idents
-
 extern crate core as bäz; //~ ERROR non-ascii idents
 
 use föö::bar; //~ ERROR non-ascii idents
diff --git a/src/test/ui/feature-gate-non_ascii_idents.stderr b/src/test/ui/feature-gate-non_ascii_idents.stderr
new file mode 100644
index 00000000000..df6ce6b6162
--- /dev/null
+++ b/src/test/ui/feature-gate-non_ascii_idents.stderr
@@ -0,0 +1,122 @@
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:11:1
+   |
+11 | extern crate core as bäz; //~ ERROR non-ascii idents
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:13:5
+   |
+13 | use föö::bar; //~ ERROR non-ascii idents
+   |     ^^^^^^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:15:1
+   |
+15 | / mod föö { //~ ERROR non-ascii idents
+16 | |     pub fn bar() {}
+17 | | }
+   | |_^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:19:1
+   |
+19 | / fn bär( //~ ERROR non-ascii idents
+20 | |     bäz: isize //~ ERROR non-ascii idents
+21 | |     ) {
+22 | |     let _ö: isize; //~ ERROR non-ascii idents
+...  |
+26 | |     }
+27 | | }
+   | |_^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:20:5
+   |
+20 |     bäz: isize //~ ERROR non-ascii idents
+   |     ^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:22:9
+   |
+22 |     let _ö: isize; //~ ERROR non-ascii idents
+   |         ^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:25:10
+   |
+25 |         (_ä, _) => {} //~ ERROR non-ascii idents
+   |          ^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:29:1
+   |
+29 | / struct Föö { //~ ERROR non-ascii idents
+30 | |     föö: isize //~ ERROR non-ascii idents
+31 | | }
+   | |_^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:30:5
+   |
+30 |     föö: isize //~ ERROR non-ascii idents
+   |     ^^^^^^^^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:33:1
+   |
+33 | / enum Bär { //~ ERROR non-ascii idents
+34 | |     Bäz { //~ ERROR non-ascii idents
+35 | |         qüx: isize //~ ERROR non-ascii idents
+36 | |     }
+37 | | }
+   | |_^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:34:5
+   |
+34 | /     Bäz { //~ ERROR non-ascii idents
+35 | |         qüx: isize //~ ERROR non-ascii idents
+36 | |     }
+   | |_____^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:35:9
+   |
+35 |         qüx: isize //~ ERROR non-ascii idents
+   |         ^^^^^^^^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: non-ascii idents are not fully supported. (see issue #28979)
+  --> $DIR/feature-gate-non_ascii_idents.rs:40:5
+   |
+40 |     fn qüx();  //~ ERROR non-ascii idents
+   |     ^^^^^^^^^
+   |
+   = help: add #![feature(non_ascii_idents)] to the crate attributes to enable
+
+error: aborting due to 13 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-non_exhaustive.rs b/src/test/ui/feature-gate-non_exhaustive.rs
index d2711084a4d..d2711084a4d 100644
--- a/src/test/compile-fail/feature-gate-non_exhaustive.rs
+++ b/src/test/ui/feature-gate-non_exhaustive.rs
diff --git a/src/test/ui/feature-gate-non_exhaustive.stderr b/src/test/ui/feature-gate-non_exhaustive.stderr
new file mode 100644
index 00000000000..775e65b90fa
--- /dev/null
+++ b/src/test/ui/feature-gate-non_exhaustive.stderr
@@ -0,0 +1,10 @@
+error: non exhaustive is an experimental feature (see issue #44109)
+  --> $DIR/feature-gate-non_exhaustive.rs:13:1
+   |
+13 | #[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(non_exhaustive)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.rs
index a837a7f213e..a837a7f213e 100644
--- a/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs
+++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.rs
diff --git a/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr
new file mode 100644
index 00000000000..e50e1b4c0b5
--- /dev/null
+++ b/src/test/ui/feature-gate-omit-gdb-pretty-printer-section.stderr
@@ -0,0 +1,10 @@
+error: the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite
+  --> $DIR/feature-gate-omit-gdb-pretty-printer-section.rs:11:1
+   |
+11 | #[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(omit_gdb_pretty_printer_section)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-on-unimplemented.rs b/src/test/ui/feature-gate-on-unimplemented.rs
index 5d32bba6a76..5d32bba6a76 100644
--- a/src/test/compile-fail/feature-gate-on-unimplemented.rs
+++ b/src/test/ui/feature-gate-on-unimplemented.rs
diff --git a/src/test/ui/feature-gate-on-unimplemented.stderr b/src/test/ui/feature-gate-on-unimplemented.stderr
new file mode 100644
index 00000000000..06944a14736
--- /dev/null
+++ b/src/test/ui/feature-gate-on-unimplemented.stderr
@@ -0,0 +1,10 @@
+error: the `#[rustc_on_unimplemented]` attribute is an experimental feature (see issue #29628)
+  --> $DIR/feature-gate-on-unimplemented.rs:14:1
+   |
+14 | #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}`"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(on_unimplemented)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs b/src/test/ui/feature-gate-optin-builtin-traits.rs
index 4c5502cec18..4c5502cec18 100644
--- a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs
+++ b/src/test/ui/feature-gate-optin-builtin-traits.rs
diff --git a/src/test/ui/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gate-optin-builtin-traits.stderr
new file mode 100644
index 00000000000..c5e9614c29a
--- /dev/null
+++ b/src/test/ui/feature-gate-optin-builtin-traits.stderr
@@ -0,0 +1,26 @@
+error: auto traits are experimental and possibly buggy (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:20:1
+   |
+20 | auto trait AutoDummyTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error: auto trait implementations are experimental and possibly buggy (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:24:1
+   |
+24 | impl DummyTrait for .. {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error: negative trait bounds are not yet fully implemented; use marker types for now (see issue #13231)
+  --> $DIR/feature-gate-optin-builtin-traits.rs:27:1
+   |
+27 | impl !DummyTrait for DummyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(optin_builtin_traits)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs b/src/test/ui/feature-gate-overlapping_marker_traits.rs
index d2aa4e59b5b..d2aa4e59b5b 100644
--- a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs
+++ b/src/test/ui/feature-gate-overlapping_marker_traits.rs
diff --git a/src/test/ui/feature-gate-overlapping_marker_traits.stderr b/src/test/ui/feature-gate-overlapping_marker_traits.stderr
new file mode 100644
index 00000000000..9028b14fcd7
--- /dev/null
+++ b/src/test/ui/feature-gate-overlapping_marker_traits.stderr
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `MyMarker`:
+  --> $DIR/feature-gate-overlapping_marker_traits.rs:16:1
+   |
+15 | impl<T: Display> MyMarker for T {}
+   | ---------------------------------- first implementation here
+16 | impl<T: Debug> MyMarker for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-placement-expr.rs b/src/test/ui/feature-gate-placement-expr.rs
index e3478876763..e3478876763 100644
--- a/src/test/compile-fail/feature-gate-placement-expr.rs
+++ b/src/test/ui/feature-gate-placement-expr.rs
diff --git a/src/test/ui/feature-gate-placement-expr.stderr b/src/test/ui/feature-gate-placement-expr.stderr
new file mode 100644
index 00000000000..fdb7b506711
--- /dev/null
+++ b/src/test/ui/feature-gate-placement-expr.stderr
@@ -0,0 +1,10 @@
+error: placement-in expression syntax is experimental and subject to change. (see issue #27779)
+  --> $DIR/feature-gate-placement-expr.rs:24:13
+   |
+24 |     let x = HEAP <- 'c'; //~ ERROR placement-in expression syntax is experimental
+   |             ^^^^^^^^^^^
+   |
+   = help: add #![feature(placement_in_syntax)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-plugin.rs b/src/test/ui/feature-gate-plugin.rs
index 3b5d7626ce3..3b5d7626ce3 100644
--- a/src/test/compile-fail/feature-gate-plugin.rs
+++ b/src/test/ui/feature-gate-plugin.rs
diff --git a/src/test/ui/feature-gate-plugin.stderr b/src/test/ui/feature-gate-plugin.stderr
new file mode 100644
index 00000000000..b94d3299abc
--- /dev/null
+++ b/src/test/ui/feature-gate-plugin.stderr
@@ -0,0 +1,10 @@
+error: compiler plugins are experimental and possibly buggy (see issue #29597)
+  --> $DIR/feature-gate-plugin.rs:13:1
+   |
+13 | #![plugin(foo)]
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(plugin)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-plugin_registrar.rs b/src/test/ui/feature-gate-plugin_registrar.rs
index 8d185d183b4..9cdebde7b7b 100644
--- a/src/test/compile-fail/gated-plugin_registrar.rs
+++ b/src/test/ui/feature-gate-plugin_registrar.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-plugin_registrar
-
 // Test that `#[plugin_registrar]` attribute is gated by `plugin_registrar`
 // feature gate.
 
diff --git a/src/test/ui/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gate-plugin_registrar.stderr
new file mode 100644
index 00000000000..3710239142a
--- /dev/null
+++ b/src/test/ui/feature-gate-plugin_registrar.stderr
@@ -0,0 +1,10 @@
+error: compiler plugins are experimental and possibly buggy (see issue #29597)
+  --> $DIR/feature-gate-plugin_registrar.rs:16:1
+   |
+16 | pub fn registrar() {}
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(plugin_registrar)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-prelude_import.rs b/src/test/ui/feature-gate-prelude_import.rs
index 8bc3df247ec..8bc3df247ec 100644
--- a/src/test/compile-fail/feature-gate-prelude_import.rs
+++ b/src/test/ui/feature-gate-prelude_import.rs
diff --git a/src/test/ui/feature-gate-prelude_import.stderr b/src/test/ui/feature-gate-prelude_import.stderr
new file mode 100644
index 00000000000..df44dfff40b
--- /dev/null
+++ b/src/test/ui/feature-gate-prelude_import.stderr
@@ -0,0 +1,10 @@
+error: `#[prelude_import]` is for use by rustc only
+  --> $DIR/feature-gate-prelude_import.rs:11:1
+   |
+11 | #[prelude_import] //~ ERROR `#[prelude_import]` is for use by rustc only
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(prelude_import)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-profiler-runtime.rs b/src/test/ui/feature-gate-profiler-runtime.rs
index c6b2cb2eb07..c6b2cb2eb07 100644
--- a/src/test/compile-fail/feature-gate-profiler-runtime.rs
+++ b/src/test/ui/feature-gate-profiler-runtime.rs
diff --git a/src/test/ui/feature-gate-profiler-runtime.stderr b/src/test/ui/feature-gate-profiler-runtime.stderr
new file mode 100644
index 00000000000..c3165438cdb
--- /dev/null
+++ b/src/test/ui/feature-gate-profiler-runtime.stderr
@@ -0,0 +1,10 @@
+error: the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate which contains the profiler runtime and will never be stable
+  --> $DIR/feature-gate-profiler-runtime.rs:11:1
+   |
+11 | #![profiler_runtime] //~ ERROR the `#[profiler_runtime]` attribute is
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(profiler_runtime)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-repr-simd.rs b/src/test/ui/feature-gate-repr-simd.rs
index 429cec7ec90..429cec7ec90 100644
--- a/src/test/compile-fail/feature-gate-repr-simd.rs
+++ b/src/test/ui/feature-gate-repr-simd.rs
diff --git a/src/test/ui/feature-gate-repr-simd.stderr b/src/test/ui/feature-gate-repr-simd.stderr
new file mode 100644
index 00000000000..a2ff06dd59f
--- /dev/null
+++ b/src/test/ui/feature-gate-repr-simd.stderr
@@ -0,0 +1,10 @@
+error: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-repr-simd.rs:11:1
+   |
+11 | #[repr(simd)] //~ error: SIMD types are experimental
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-repr128.rs b/src/test/ui/feature-gate-repr128.rs
index 96fffa6cdd0..96fffa6cdd0 100644
--- a/src/test/compile-fail/feature-gate-repr128.rs
+++ b/src/test/ui/feature-gate-repr128.rs
diff --git a/src/test/ui/feature-gate-repr128.stderr b/src/test/ui/feature-gate-repr128.stderr
new file mode 100644
index 00000000000..2d32eda3b37
--- /dev/null
+++ b/src/test/ui/feature-gate-repr128.stderr
@@ -0,0 +1,13 @@
+error: repr with 128-bit type is unstable (see issue #35118)
+  --> $DIR/feature-gate-repr128.rs:12:1
+   |
+12 | / enum A { //~ ERROR repr with 128-bit type is unstable
+13 | |     //~| HELP: add #![feature(repr128)]
+14 | |     A(u64)
+15 | | }
+   | |_^
+   |
+   = help: add #![feature(repr128)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-repr_align.rs b/src/test/ui/feature-gate-repr_align.rs
index 9591d367a2d..9591d367a2d 100644
--- a/src/test/compile-fail/feature-gate-repr_align.rs
+++ b/src/test/ui/feature-gate-repr_align.rs
diff --git a/src/test/ui/feature-gate-repr_align.stderr b/src/test/ui/feature-gate-repr_align.stderr
new file mode 100644
index 00000000000..16fdc135a5f
--- /dev/null
+++ b/src/test/ui/feature-gate-repr_align.stderr
@@ -0,0 +1,10 @@
+error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
+  --> $DIR/feature-gate-repr_align.rs:12:1
+   |
+12 | #[repr(align(64))] //~ error: the struct `#[repr(align(u16))]` attribute is experimental
+   | ^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_align)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gate-rustc-attrs.rs
index 8cfd3e020c6..8cfd3e020c6 100644
--- a/src/test/compile-fail/feature-gate-rustc-attrs.rs
+++ b/src/test/ui/feature-gate-rustc-attrs.rs
diff --git a/src/test/ui/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gate-rustc-attrs.stderr
new file mode 100644
index 00000000000..c818b57ef12
--- /dev/null
+++ b/src/test/ui/feature-gate-rustc-attrs.stderr
@@ -0,0 +1,26 @@
+error: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs.rs:15:1
+   |
+15 | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs.rs:16:1
+   |
+16 | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+   | ^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
+  --> $DIR/feature-gate-rustc-attrs.rs:17:1
+   |
+17 | #[rustc_foo]
+   | ^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs b/src/test/ui/feature-gate-rustc-diagnostic-macros.rs
index bbdf248780f..bbdf248780f 100644
--- a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs
+++ b/src/test/ui/feature-gate-rustc-diagnostic-macros.rs
diff --git a/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr
new file mode 100644
index 00000000000..843879036ed
--- /dev/null
+++ b/src/test/ui/feature-gate-rustc-diagnostic-macros.stderr
@@ -0,0 +1,20 @@
+error: cannot find macro `__build_diagnostic_array!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:22:1
+   |
+22 | __build_diagnostic_array!(DIAGNOSTICS);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find macro `__register_diagnostic!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:14:1
+   |
+14 | __register_diagnostic!(E0001);
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find macro `__diagnostic_used!` in this scope
+  --> $DIR/feature-gate-rustc-diagnostic-macros.rs:18:5
+   |
+18 |     __diagnostic_used!(E0001);
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-rustc_const_unstable.rs b/src/test/ui/feature-gate-rustc_const_unstable.rs
index 38a3e15fd7e..38a3e15fd7e 100644
--- a/src/test/compile-fail/feature-gate-rustc_const_unstable.rs
+++ b/src/test/ui/feature-gate-rustc_const_unstable.rs
diff --git a/src/test/ui/feature-gate-rustc_const_unstable.stderr b/src/test/ui/feature-gate-rustc_const_unstable.stderr
new file mode 100644
index 00000000000..c32abb8b857
--- /dev/null
+++ b/src/test/ui/feature-gate-rustc_const_unstable.stderr
@@ -0,0 +1,10 @@
+error: the `#[rustc_const_unstable]` attribute is an internal feature
+  --> $DIR/feature-gate-rustc_const_unstable.rs:18:1
+   |
+18 | #[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(rustc_const_unstable)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gate-sanitizer-runtime.rs
index a18641d8246..a18641d8246 100644
--- a/src/test/compile-fail/feature-gate-sanitizer-runtime.rs
+++ b/src/test/ui/feature-gate-sanitizer-runtime.rs
diff --git a/src/test/ui/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gate-sanitizer-runtime.stderr
new file mode 100644
index 00000000000..b9a43f8098d
--- /dev/null
+++ b/src/test/ui/feature-gate-sanitizer-runtime.stderr
@@ -0,0 +1,10 @@
+error: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable
+  --> $DIR/feature-gate-sanitizer-runtime.rs:11:1
+   |
+11 | #![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(sanitizer_runtime)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/ui/feature-gate-simd-ffi.rs
index 31c055f229c..31c055f229c 100644
--- a/src/test/compile-fail/feature-gate-simd-ffi.rs
+++ b/src/test/ui/feature-gate-simd-ffi.rs
diff --git a/src/test/ui/feature-gate-simd-ffi.stderr b/src/test/ui/feature-gate-simd-ffi.stderr
new file mode 100644
index 00000000000..fa47e1a2903
--- /dev/null
+++ b/src/test/ui/feature-gate-simd-ffi.stderr
@@ -0,0 +1,18 @@
+error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
+  --> $DIR/feature-gate-simd-ffi.rs:20:17
+   |
+20 |     fn baz() -> LocalSimd; //~ ERROR use of SIMD type
+   |                 ^^^^^^^^^
+   |
+   = help: add #![feature(simd_ffi)] to the crate attributes to enable
+
+error: use of SIMD type `LocalSimd` in FFI is highly experimental and may result in invalid code
+  --> $DIR/feature-gate-simd-ffi.rs:21:15
+   |
+21 |     fn qux(x: LocalSimd); //~ ERROR use of SIMD type
+   |               ^^^^^^^^^
+   |
+   = help: add #![feature(simd_ffi)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-simd.rs b/src/test/ui/feature-gate-simd.rs
index 025eaca5533..025eaca5533 100644
--- a/src/test/compile-fail/feature-gate-simd.rs
+++ b/src/test/ui/feature-gate-simd.rs
diff --git a/src/test/ui/feature-gate-simd.stderr b/src/test/ui/feature-gate-simd.stderr
new file mode 100644
index 00000000000..b3225d580bf
--- /dev/null
+++ b/src/test/ui/feature-gate-simd.stderr
@@ -0,0 +1,10 @@
+error: SIMD types are experimental and possibly buggy (see issue #27731)
+  --> $DIR/feature-gate-simd.rs:14:1
+   |
+14 | #[repr(simd)] //~ ERROR SIMD types are experimental
+   | ^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_simd)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-slice-patterns.rs b/src/test/ui/feature-gate-slice-patterns.rs
index 625cb2d3515..625cb2d3515 100644
--- a/src/test/compile-fail/feature-gate-slice-patterns.rs
+++ b/src/test/ui/feature-gate-slice-patterns.rs
diff --git a/src/test/ui/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gate-slice-patterns.stderr
new file mode 100644
index 00000000000..e5ba318b336
--- /dev/null
+++ b/src/test/ui/feature-gate-slice-patterns.stderr
@@ -0,0 +1,10 @@
+error: slice pattern syntax is experimental (see issue #23121)
+  --> $DIR/feature-gate-slice-patterns.rs:16:9
+   |
+16 |         [1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
+   |         ^^^^^^^^^^^^
+   |
+   = help: add #![feature(slice_patterns)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-staged_api.rs b/src/test/ui/feature-gate-staged_api.rs
index 014a0aaaf68..014a0aaaf68 100644
--- a/src/test/compile-fail/feature-gate-staged_api.rs
+++ b/src/test/ui/feature-gate-staged_api.rs
diff --git a/src/test/ui/feature-gate-staged_api.stderr b/src/test/ui/feature-gate-staged_api.stderr
new file mode 100644
index 00000000000..30593d45760
--- /dev/null
+++ b/src/test/ui/feature-gate-staged_api.stderr
@@ -0,0 +1,14 @@
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/feature-gate-staged_api.rs:11:1
+   |
+11 | #![stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/feature-gate-staged_api.rs:18:1
+   |
+18 | #[stable(feature = "a", since = "b")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-start.rs b/src/test/ui/feature-gate-start.rs
index 7a0924d8adf..7a0924d8adf 100644
--- a/src/test/compile-fail/feature-gate-start.rs
+++ b/src/test/ui/feature-gate-start.rs
diff --git a/src/test/ui/feature-gate-start.stderr b/src/test/ui/feature-gate-start.stderr
new file mode 100644
index 00000000000..b36fae2aacf
--- /dev/null
+++ b/src/test/ui/feature-gate-start.stderr
@@ -0,0 +1,10 @@
+error: a #[start] function is an experimental feature whose signature may change over time (see issue #29633)
+  --> $DIR/feature-gate-start.rs:12:1
+   |
+12 | fn foo() {} //~ ERROR: a #[start] function is an experimental feature
+   | ^^^^^^^^^^^
+   |
+   = help: add #![feature(start)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/ui/feature-gate-static-nobundle.rs
index 0d13a4937c4..0d13a4937c4 100644
--- a/src/test/compile-fail/feature-gate-static-nobundle.rs
+++ b/src/test/ui/feature-gate-static-nobundle.rs
diff --git a/src/test/ui/feature-gate-static-nobundle.stderr b/src/test/ui/feature-gate-static-nobundle.stderr
new file mode 100644
index 00000000000..052516fad76
--- /dev/null
+++ b/src/test/ui/feature-gate-static-nobundle.stderr
@@ -0,0 +1,10 @@
+error: kind="static-nobundle" is feature gated (see issue #37403)
+  --> $DIR/feature-gate-static-nobundle.rs:11:1
+   |
+11 | #[link(name="foo", kind="static-nobundle")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(static_nobundle)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-stmt_expr_attributes.rs b/src/test/ui/feature-gate-stmt_expr_attributes.rs
index 831d8862e10..831d8862e10 100644
--- a/src/test/compile-fail/feature-gate-stmt_expr_attributes.rs
+++ b/src/test/ui/feature-gate-stmt_expr_attributes.rs
diff --git a/src/test/ui/feature-gate-stmt_expr_attributes.stderr b/src/test/ui/feature-gate-stmt_expr_attributes.stderr
new file mode 100644
index 00000000000..80910594d1c
--- /dev/null
+++ b/src/test/ui/feature-gate-stmt_expr_attributes.stderr
@@ -0,0 +1,10 @@
+error: attributes on non-item statements and expressions are experimental. (see issue #15701)
+  --> $DIR/feature-gate-stmt_expr_attributes.rs:11:16
+   |
+11 | const X: i32 = #[allow(dead_code)] 8;
+   |                ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(stmt_expr_attributes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-target_feature.rs b/src/test/ui/feature-gate-target_feature.rs
index 02db8a71d53..da2e41a0f5e 100644
--- a/src/test/compile-fail/gated-target_feature.rs
+++ b/src/test/ui/feature-gate-target_feature.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-target_feature
-
 #[target_feature = "+sse2"]
 //~^ the `#[target_feature]` attribute is an experimental feature
 fn foo() {}
diff --git a/src/test/ui/feature-gate-target_feature.stderr b/src/test/ui/feature-gate-target_feature.stderr
new file mode 100644
index 00000000000..8c89eabf753
--- /dev/null
+++ b/src/test/ui/feature-gate-target_feature.stderr
@@ -0,0 +1,10 @@
+error: the `#[target_feature]` attribute is an experimental feature
+  --> $DIR/feature-gate-target_feature.rs:11:1
+   |
+11 | #[target_feature = "+sse2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(target_feature)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-thread-local.rs b/src/test/ui/feature-gate-thread_local.rs
index b02ce9b7ecb..f355c6562c8 100644
--- a/src/test/compile-fail/gated-thread-local.rs
+++ b/src/test/ui/feature-gate-thread_local.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-thread_local
-
 // Test that `#[thread_local]` attribute is gated by `thread_local`
 // feature gate.
 //
diff --git a/src/test/ui/feature-gate-thread_local.stderr b/src/test/ui/feature-gate-thread_local.stderr
new file mode 100644
index 00000000000..2608018528c
--- /dev/null
+++ b/src/test/ui/feature-gate-thread_local.stderr
@@ -0,0 +1,10 @@
+error: `#[thread_local]` is an experimental feature, and does not currently handle destructors. There is no corresponding `#[task_local]` mapping to the task model (see issue #29594)
+  --> $DIR/feature-gate-thread_local.rs:18:1
+   |
+18 | #[thread_local] //~ ERROR `#[thread_local]` is an experimental feature
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(thread_local)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/gated-trace_macros.rs b/src/test/ui/feature-gate-trace_macros.rs
index 0b85b19f176..367ee6df50d 100644
--- a/src/test/compile-fail/gated-trace_macros.rs
+++ b/src/test/ui/feature-gate-trace_macros.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-trace_macros
-
 fn main() {
     trace_macros!(true); //~ ERROR: `trace_macros` is not stable
 }
diff --git a/src/test/ui/feature-gate-trace_macros.stderr b/src/test/ui/feature-gate-trace_macros.stderr
new file mode 100644
index 00000000000..aca74099b7d
--- /dev/null
+++ b/src/test/ui/feature-gate-trace_macros.stderr
@@ -0,0 +1,10 @@
+error: `trace_macros` is not stable enough for use and is subject to change (see issue #29598)
+  --> $DIR/feature-gate-trace_macros.rs:12:5
+   |
+12 |     trace_macros!(true); //~ ERROR: `trace_macros` is not stable
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(trace_macros)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/type-ascription-feature-gate.rs b/src/test/ui/feature-gate-type_ascription.rs
index bf4ca03069c..d3c07d653f4 100644
--- a/src/test/compile-fail/type-ascription-feature-gate.rs
+++ b/src/test/ui/feature-gate-type_ascription.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-type_ascription
-
 // Type ascription is feature gated
 
 fn main() {
diff --git a/src/test/ui/feature-gate-type_ascription.stderr b/src/test/ui/feature-gate-type_ascription.stderr
new file mode 100644
index 00000000000..d2a3ee2cf8f
--- /dev/null
+++ b/src/test/ui/feature-gate-type_ascription.stderr
@@ -0,0 +1,10 @@
+error: type ascription is experimental (see issue #23416)
+  --> $DIR/feature-gate-type_ascription.rs:14:13
+   |
+14 |     let a = 10: u8; //~ ERROR type ascription is experimental
+   |             ^^^^^^
+   |
+   = help: add #![feature(type_ascription)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs b/src/test/ui/feature-gate-unboxed-closures-manual-impls.rs
index 5df309321d3..5df309321d3 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
+++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.rs
diff --git a/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr
new file mode 100644
index 00000000000..280fc12f1a6
--- /dev/null
+++ b/src/test/ui/feature-gate-unboxed-closures-manual-impls.stderr
@@ -0,0 +1,34 @@
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:20:5
+   |
+20 |     extern "rust-call" fn call(self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:25:5
+   |
+25 |     extern "rust-call" fn call_once(self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:5
+   |
+30 |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:35:5
+   |
+35 |     extern "rust-call" fn call_once(&self, args: ()) -> () {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs b/src/test/ui/feature-gate-unboxed-closures-method-calls.rs
index 253d1633b1c..253d1633b1c 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-method-calls.rs
+++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.rs
diff --git a/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr
new file mode 100644
index 00000000000..1167bf0a696
--- /dev/null
+++ b/src/test/ui/feature-gate-unboxed-closures-method-calls.stderr
@@ -0,0 +1,26 @@
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:14:7
+   |
+14 |     f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
+   |       ^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:15:7
+   |
+15 |     f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
+   |       ^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-method-calls.rs:16:7
+   |
+16 |     f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
+   |       ^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.rs
index 902b3c1774c..902b3c1774c 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures-ufcs-calls.rs
+++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.rs
diff --git a/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr
new file mode 100644
index 00000000000..7eb491cebfe
--- /dev/null
+++ b/src/test/ui/feature-gate-unboxed-closures-ufcs-calls.stderr
@@ -0,0 +1,26 @@
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:14:5
+   |
+14 |     Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+   |     ^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:15:5
+   |
+15 |     FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: use of unstable library feature 'fn_traits' (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:16:5
+   |
+16 |     FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(fn_traits)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-unboxed-closures.rs b/src/test/ui/feature-gate-unboxed-closures.rs
index 40050217744..40050217744 100644
--- a/src/test/compile-fail/feature-gate-unboxed-closures.rs
+++ b/src/test/ui/feature-gate-unboxed-closures.rs
diff --git a/src/test/ui/feature-gate-unboxed-closures.stderr b/src/test/ui/feature-gate-unboxed-closures.stderr
new file mode 100644
index 00000000000..b79165147e5
--- /dev/null
+++ b/src/test/ui/feature-gate-unboxed-closures.stderr
@@ -0,0 +1,12 @@
+error: rust-call ABI is subject to change (see issue #29625)
+  --> $DIR/feature-gate-unboxed-closures.rs:16:5
+   |
+16 | /     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
+17 | |         a + b
+18 | |     }
+   | |_____^
+   |
+   = help: add #![feature(unboxed_closures)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-underscore-lifetimes.rs b/src/test/ui/feature-gate-underscore-lifetimes.rs
index 9da50c5c877..9da50c5c877 100644
--- a/src/test/compile-fail/feature-gate-underscore-lifetimes.rs
+++ b/src/test/ui/feature-gate-underscore-lifetimes.rs
diff --git a/src/test/ui/feature-gate-underscore-lifetimes.stderr b/src/test/ui/feature-gate-underscore-lifetimes.stderr
new file mode 100644
index 00000000000..875b958aa88
--- /dev/null
+++ b/src/test/ui/feature-gate-underscore-lifetimes.stderr
@@ -0,0 +1,10 @@
+error: underscore lifetimes are unstable (see issue #44524)
+  --> $DIR/feature-gate-underscore-lifetimes.rs:13:23
+   |
+13 | fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable
+   |                       ^^
+   |
+   = help: add #![feature(underscore_lifetimes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/impl-trait/feature-gate-universal.rs b/src/test/ui/feature-gate-universal.rs
index e5bdf3a42eb..e5bdf3a42eb 100644
--- a/src/test/compile-fail/impl-trait/feature-gate-universal.rs
+++ b/src/test/ui/feature-gate-universal.rs
diff --git a/src/test/ui/feature-gate-universal.stderr b/src/test/ui/feature-gate-universal.stderr
new file mode 100644
index 00000000000..7f889f96224
--- /dev/null
+++ b/src/test/ui/feature-gate-universal.stderr
@@ -0,0 +1,10 @@
+error: `impl Trait` in argument position is experimental (see issue #34511)
+  --> $DIR/feature-gate-universal.rs:13:11
+   |
+13 | fn foo(x: impl std::fmt::Debug) { print!("{:?}", x); }
+   |           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(universal_impl_trait)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/ui/feature-gate-unsized_tuple_coercion.rs
index 4ddde011263..4ddde011263 100644
--- a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
+++ b/src/test/ui/feature-gate-unsized_tuple_coercion.rs
diff --git a/src/test/ui/feature-gate-unsized_tuple_coercion.stderr b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr
new file mode 100644
index 00000000000..f166b10613a
--- /dev/null
+++ b/src/test/ui/feature-gate-unsized_tuple_coercion.stderr
@@ -0,0 +1,10 @@
+error: Unsized tuple coercion is not stable enough for use and is subject to change (see issue #42877)
+  --> $DIR/feature-gate-unsized_tuple_coercion.rs:12:24
+   |
+12 |     let _ : &(Send,) = &((),);
+   |                        ^^^^^^
+   |
+   = help: add #![feature(unsized_tuple_coercion)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/union/union-feature-gate.rs b/src/test/ui/feature-gate-untagged_unions.rs
index 8a0490cdc6b..6533fddd947 100644
--- a/src/test/compile-fail/union/union-feature-gate.rs
+++ b/src/test/ui/feature-gate-untagged_unions.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// gate-test-untagged_unions
-
 union U1 { // OK
     a: u8,
 }
diff --git a/src/test/ui/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gate-untagged_unions.stderr
new file mode 100644
index 00000000000..26b698912bc
--- /dev/null
+++ b/src/test/ui/feature-gate-untagged_unions.stderr
@@ -0,0 +1,32 @@
+error: unions with non-`Copy` fields are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:19:1
+   |
+19 | / union U3 { //~ ERROR unions with non-`Copy` fields are unstable
+20 | |     a: String,
+21 | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error: unions with non-`Copy` fields are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:23:1
+   |
+23 | / union U4<T> { //~ ERROR unions with non-`Copy` fields are unstable
+24 | |     a: T,
+25 | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error: unions with `Drop` implementations are unstable (see issue #32836)
+  --> $DIR/feature-gate-untagged_unions.rs:27:1
+   |
+27 | / union U5 { //~ ERROR unions with `Drop` implementations are unstable
+28 | |     a: u8,
+29 | | }
+   | |_^
+   |
+   = help: add #![feature(untagged_unions)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gate-unwind-attributes.rs
index c8f9cd943cd..c8f9cd943cd 100644
--- a/src/test/compile-fail/feature-gate-unwind-attributes.rs
+++ b/src/test/ui/feature-gate-unwind-attributes.rs
diff --git a/src/test/ui/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gate-unwind-attributes.stderr
new file mode 100644
index 00000000000..02d8bf914eb
--- /dev/null
+++ b/src/test/ui/feature-gate-unwind-attributes.stderr
@@ -0,0 +1,10 @@
+error: #[unwind] is experimental
+  --> $DIR/feature-gate-unwind-attributes.rs:21:5
+   |
+21 |     #[unwind] //~ ERROR #[unwind] is experimental
+   |     ^^^^^^^^^
+   |
+   = help: add #![feature(unwind_attributes)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-use_nested_groups.rs b/src/test/ui/feature-gate-use_nested_groups.rs
index 56413a999d7..56413a999d7 100644
--- a/src/test/compile-fail/feature-gate-use_nested_groups.rs
+++ b/src/test/ui/feature-gate-use_nested_groups.rs
diff --git a/src/test/ui/feature-gate-use_nested_groups.stderr b/src/test/ui/feature-gate-use_nested_groups.stderr
new file mode 100644
index 00000000000..79f1d1a168f
--- /dev/null
+++ b/src/test/ui/feature-gate-use_nested_groups.stderr
@@ -0,0 +1,26 @@
+error: nested groups in `use` are experimental (see issue #44494)
+  --> $DIR/feature-gate-use_nested_groups.rs:27:12
+   |
+27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
+   |            ^^^^^^^^^^^^
+   |
+   = help: add #![feature(use_nested_groups)] to the crate attributes to enable
+
+error: glob imports in `use` groups are experimental (see issue #44494)
+  --> $DIR/feature-gate-use_nested_groups.rs:27:16
+   |
+27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
+   |                ^
+   |
+   = help: add #![feature(use_nested_groups)] to the crate attributes to enable
+
+error: paths in `use` groups are experimental (see issue #44494)
+  --> $DIR/feature-gate-use_nested_groups.rs:27:19
+   |
+27 | use a::{B, d::{*, g::H}};  //~ ERROR glob imports in `use` groups are experimental
+   |                   ^^^^
+   |
+   = help: add #![feature(use_nested_groups)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate-used.rs b/src/test/ui/feature-gate-used.rs
index 68679d7dac8..68679d7dac8 100644
--- a/src/test/compile-fail/feature-gate-used.rs
+++ b/src/test/ui/feature-gate-used.rs
diff --git a/src/test/ui/feature-gate-used.stderr b/src/test/ui/feature-gate-used.stderr
new file mode 100644
index 00000000000..228cf12a08b
--- /dev/null
+++ b/src/test/ui/feature-gate-used.stderr
@@ -0,0 +1,10 @@
+error: the `#[used]` attribute is an experimental feature (see issue #40289)
+  --> $DIR/feature-gate-used.rs:11:1
+   |
+11 | #[used]
+   | ^^^^^^^
+   |
+   = help: add #![feature(used)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-wasm_import_memory.rs b/src/test/ui/feature-gate-wasm_import_memory.rs
index a010ebb3551..a010ebb3551 100644
--- a/src/test/compile-fail/feature-gate-wasm_import_memory.rs
+++ b/src/test/ui/feature-gate-wasm_import_memory.rs
diff --git a/src/test/ui/feature-gate-wasm_import_memory.stderr b/src/test/ui/feature-gate-wasm_import_memory.stderr
new file mode 100644
index 00000000000..c0486d0d5f5
--- /dev/null
+++ b/src/test/ui/feature-gate-wasm_import_memory.stderr
@@ -0,0 +1,10 @@
+error: wasm_import_memory attribute is currently unstable
+  --> $DIR/feature-gate-wasm_import_memory.rs:11:1
+   |
+11 | #![wasm_import_memory] //~ ERROR: currently unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(wasm_import_memory)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-bench.rs b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
index a34f98f0355..a34f98f0355 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-bench.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
new file mode 100644
index 00000000000..f7d5473f443
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-bench.stderr
@@ -0,0 +1,4 @@
+error[E0601]: main function not found
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index ab2fe02bb14..ab2fe02bb14 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
new file mode 100644
index 00000000000..0e72442143b
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -0,0 +1,1354 @@
+warning: macro_escape is a deprecated synonym for macro_use
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1
+    |
+532 | #[macro_escape]
+    | ^^^^^^^^^^^^^^^
+
+warning: macro_escape is a deprecated synonym for macro_use
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:17
+    |
+535 |     mod inner { #![macro_escape] }
+    |                 ^^^^^^^^^^^^^^^^
+    |
+    = help: consider an outer attribute, #[macro_use] mod ...
+
+warning: `#[must_use]` on functions is experimental (see issue #43302)
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
+    |
+682 |     #[must_use = "1400"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^
+    |
+    = help: add #![feature(fn_must_use)] to the crate attributes to enable
+
+warning: unknown lint: `x5400`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33
+   |
+49 | #![warn                        (x5400)] //~ WARN unknown lint: `x5400`
+   |                                 ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:28
+   |
+44 | #![warn(unused_attributes, unknown_lints)]
+   |                            ^^^^^^^^^^^^^
+
+warning: unknown lint: `x5300`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:33
+   |
+50 | #![allow                       (x5300)] //~ WARN unknown lint: `x5300`
+   |                                 ^^^^^
+
+warning: unknown lint: `x5200`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:51:33
+   |
+51 | #![forbid                      (x5200)] //~ WARN unknown lint: `x5200`
+   |                                 ^^^^^
+
+warning: unknown lint: `x5100`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:52:33
+   |
+52 | #![deny                        (x5100)] //~ WARN unknown lint: `x5100`
+   |                                 ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:8
+    |
+114 | #[warn(x5400)]
+    |        ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:25
+    |
+117 |     mod inner { #![warn(x5400)] }
+    |                         ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12
+    |
+120 |     #[warn(x5400)] fn f() { }
+    |            ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:123:12
+    |
+123 |     #[warn(x5400)] struct S;
+    |            ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:126:12
+    |
+126 |     #[warn(x5400)] type T = S;
+    |            ^^^^^
+
+warning: unknown lint: `x5400`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:129:12
+    |
+129 |     #[warn(x5400)] impl S { }
+    |            ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:9
+    |
+133 | #[allow(x5300)]
+    |         ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:26
+    |
+136 |     mod inner { #![allow(x5300)] }
+    |                          ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13
+    |
+139 |     #[allow(x5300)] fn f() { }
+    |             ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:142:13
+    |
+142 |     #[allow(x5300)] struct S;
+    |             ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:145:13
+    |
+145 |     #[allow(x5300)] type T = S;
+    |             ^^^^^
+
+warning: unknown lint: `x5300`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:148:13
+    |
+148 |     #[allow(x5300)] impl S { }
+    |             ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:10
+    |
+152 | #[forbid(x5200)]
+    |          ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:27
+    |
+155 |     mod inner { #![forbid(x5200)] }
+    |                           ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14
+    |
+158 |     #[forbid(x5200)] fn f() { }
+    |              ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:161:14
+    |
+161 |     #[forbid(x5200)] struct S;
+    |              ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:164:14
+    |
+164 |     #[forbid(x5200)] type T = S;
+    |              ^^^^^
+
+warning: unknown lint: `x5200`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:167:14
+    |
+167 |     #[forbid(x5200)] impl S { }
+    |              ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:8
+    |
+171 | #[deny(x5100)]
+    |        ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:25
+    |
+174 |     mod inner { #![deny(x5100)] }
+    |                         ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12
+    |
+177 |     #[deny(x5100)] fn f() { }
+    |            ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:180:12
+    |
+180 |     #[deny(x5100)] struct S;
+    |            ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:12
+    |
+183 |     #[deny(x5100)] type T = S;
+    |            ^^^^^
+
+warning: unknown lint: `x5100`
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:186:12
+    |
+186 |     #[deny(x5100)] impl S { }
+    |            ^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:17
+    |
+193 |     mod inner { #![macro_reexport="5000"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+    |
+note: lint level defined here
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9
+    |
+44  | #![warn(unused_attributes, unknown_lints)]
+    |         ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:196:5
+    |
+196 |     #[macro_reexport = "5000"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:199:5
+    |
+199 |     #[macro_reexport = "5000"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:202:5
+    |
+202 |     #[macro_reexport = "5000"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:5
+    |
+205 |     #[macro_reexport = "5000"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:190:1
+    |
+190 | #[macro_reexport = "5000"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5
+    |
+213 |     #[macro_use] fn f() { }
+    |     ^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5
+    |
+216 |     #[macro_use] struct S;
+    |     ^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5
+    |
+219 |     #[macro_use] type T = S;
+    |     ^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:222:5
+    |
+222 |     #[macro_use] impl S { }
+    |     ^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:229:17
+    |
+229 |     mod inner { #![macro_export="4800"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5
+    |
+232 |     #[macro_export = "4800"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5
+    |
+235 |     #[macro_export = "4800"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5
+    |
+238 |     #[macro_export = "4800"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:241:5
+    |
+241 |     #[macro_export = "4800"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:226:1
+    |
+226 | #[macro_export = "4800"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:248:17
+    |
+248 |     mod inner { #![plugin_registrar="4700"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5
+    |
+253 |     #[plugin_registrar = "4700"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5
+    |
+256 |     #[plugin_registrar = "4700"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5
+    |
+259 |     #[plugin_registrar = "4700"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:1
+    |
+245 | #[plugin_registrar = "4700"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:17
+    |
+266 |     mod inner { #![main="4300"] }
+    |                 ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
+    |
+271 |     #[main = "4400"] struct S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5
+    |
+274 |     #[main = "4400"] type T = S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:277:5
+    |
+277 |     #[main = "4400"] impl S { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:1
+    |
+263 | #[main = "4400"]
+    | ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:17
+    |
+284 |     mod inner { #![start="4300"] }
+    |                 ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:5
+    |
+289 |     #[start = "4300"] struct S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5
+    |
+292 |     #[start = "4300"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5
+    |
+295 |     #[start = "4300"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1
+    |
+281 | #[start = "4300"]
+    | ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:17
+    |
+334 |     mod inner { #![simd="4000"] }
+    |                 ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:337:5
+    |
+337 |     #[simd = "4000"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:5
+    |
+342 |     #[simd = "4000"] type T = S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:5
+    |
+345 |     #[simd = "4000"] impl S { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:331:1
+    |
+331 | #[simd = "4000"]
+    | ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:17
+    |
+352 |     mod inner { #![repr="3900"] }
+    |                 ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
+    |
+355 |     #[repr = "3900"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5
+    |
+360 |     #[repr = "3900"] type T = S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:5
+    |
+363 |     #[repr = "3900"] impl S { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:349:1
+    |
+349 | #[repr = "3900"]
+    | ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5
+    |
+371 |     #[path = "3800"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5
+    |
+374 |     #[path = "3800"]  struct S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5
+    |
+377 |     #[path = "3800"] type T = S;
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5
+    |
+380 |     #[path = "3800"] impl S { }
+    |     ^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17
+    |
+387 |     mod inner { #![abi="3700"] }
+    |                 ^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5
+    |
+390 |     #[abi = "3700"] fn f() { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5
+    |
+393 |     #[abi = "3700"] struct S;
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5
+    |
+396 |     #[abi = "3700"] type T = S;
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5
+    |
+399 |     #[abi = "3700"] impl S { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1
+    |
+384 | #[abi = "3700"]
+    | ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:17
+    |
+406 |     mod inner { #![automatically_derived="3600"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5
+    |
+409 |     #[automatically_derived = "3600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5
+    |
+412 |     #[automatically_derived = "3600"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:415:5
+    |
+415 |     #[automatically_derived = "3600"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5
+    |
+418 |     #[automatically_derived = "3600"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:1
+    |
+403 | #[automatically_derived = "3600"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: function is marked #[no_mangle], but not exported
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:27
+    |
+426 |     #[no_mangle = "3500"] fn f() { }
+    |                           -^^^^^^^^^
+    |                           |
+    |                           help: try making it public: `pub `
+    |
+    = note: #[warn(private_no_mangle_fns)] on by default
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17
+    |
+439 |     mod inner { #![no_link="3400"] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5
+    |
+442 |     #[no_link = "3400"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5
+    |
+445 |     #[no_link = "3400"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
+    |
+448 |     #[no_link = "3400"]type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
+    |
+451 |     #[no_link = "3400"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1
+    |
+436 | #[no_link = "3400"]
+    | ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17
+    |
+458 |     mod inner { #![should_panic="3200"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5
+    |
+461 |     #[should_panic = "3200"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
+    |
+464 |     #[should_panic = "3200"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
+    |
+467 |     #[should_panic = "3200"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
+    |
+470 |     #[should_panic = "3200"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1
+    |
+455 | #[should_panic = "3200"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17
+    |
+477 |     mod inner { #![ignore="3100"] }
+    |                 ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5
+    |
+480 |     #[ignore = "3100"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5
+    |
+483 |     #[ignore = "3100"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
+    |
+486 |     #[ignore = "3100"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+    |
+489 |     #[ignore = "3100"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1
+    |
+474 | #[ignore = "3100"]
+    | ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17
+    |
+496 |     mod inner { #![no_implicit_prelude="3000"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5
+    |
+499 |     #[no_implicit_prelude = "3000"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
+    |
+502 |     #[no_implicit_prelude = "3000"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5
+    |
+505 |     #[no_implicit_prelude = "3000"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5
+    |
+508 |     #[no_implicit_prelude = "3000"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1
+    |
+493 | #[no_implicit_prelude = "3000"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:17
+    |
+515 |     mod inner { #![reexport_test_harness_main="2900"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5
+    |
+518 |     #[reexport_test_harness_main = "2900"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
+    |
+521 |     #[reexport_test_harness_main = "2900"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5
+    |
+524 |     #[reexport_test_harness_main = "2900"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
+    |
+527 |     #[reexport_test_harness_main = "2900"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1
+    |
+512 | #[reexport_test_harness_main = "2900"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:5
+    |
+538 |     #[macro_escape] fn f() { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+    |
+541 |     #[macro_escape] struct S;
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+    |
+544 |     #[macro_escape] type T = S;
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
+    |
+547 |     #[macro_escape] impl S { }
+    |     ^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+    |
+555 |     mod inner { #![no_std="2600"] }
+    |                 ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:17
+    |
+555 |     mod inner { #![no_std="2600"] }
+    |                 ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+    |
+559 |     #[no_std = "2600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
+    |
+559 |     #[no_std = "2600"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+    |
+563 |     #[no_std = "2600"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:5
+    |
+563 |     #[no_std = "2600"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+    |
+567 |     #[no_std = "2600"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:567:5
+    |
+567 |     #[no_std = "2600"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+    |
+571 |     #[no_std = "2600"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5
+    |
+571 |     #[no_std = "2600"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+    |
+551 | #[no_std = "2600"]
+    | ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:1
+    |
+551 | #[no_std = "2600"]
+    | ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+    |
+711 |     mod inner { #![crate_name="0900"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:17
+    |
+711 |     mod inner { #![crate_name="0900"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+    |
+715 |     #[crate_name = "0900"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
+    |
+715 |     #[crate_name = "0900"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+    |
+719 |     #[crate_name = "0900"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
+    |
+719 |     #[crate_name = "0900"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+    |
+723 |     #[crate_name = "0900"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:5
+    |
+723 |     #[crate_name = "0900"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+    |
+727 |     #[crate_name = "0900"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5
+    |
+727 |     #[crate_name = "0900"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+    |
+707 | #[crate_name = "0900"]
+    | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:1
+    |
+707 | #[crate_name = "0900"]
+    | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+    |
+736 |     mod inner { #![crate_type="0800"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:17
+    |
+736 |     mod inner { #![crate_type="0800"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+    |
+740 |     #[crate_type = "0800"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
+    |
+740 |     #[crate_type = "0800"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+    |
+744 |     #[crate_type = "0800"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
+    |
+744 |     #[crate_type = "0800"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+    |
+748 |     #[crate_type = "0800"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:5
+    |
+748 |     #[crate_type = "0800"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+    |
+752 |     #[crate_type = "0800"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5
+    |
+752 |     #[crate_type = "0800"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+    |
+732 | #[crate_type = "0800"]
+    | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:1
+    |
+732 | #[crate_type = "0800"]
+    | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+    |
+761 |     mod inner { #![feature(x0600)] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:17
+    |
+761 |     mod inner { #![feature(x0600)] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+    |
+765 |     #[feature(x0600)] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
+    |
+765 |     #[feature(x0600)] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+    |
+769 |     #[feature(x0600)] struct S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:5
+    |
+769 |     #[feature(x0600)] struct S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+    |
+773 |     #[feature(x0600)] type T = S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
+    |
+773 |     #[feature(x0600)] type T = S;
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+    |
+777 |     #[feature(x0600)] impl S { }
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:777:5
+    |
+777 |     #[feature(x0600)] impl S { }
+    |     ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+    |
+757 | #[feature(x0600)]
+    | ^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1
+    |
+757 | #[feature(x0600)]
+    | ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+    |
+787 |     mod inner { #![no_main="0400"] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:787:17
+    |
+787 |     mod inner { #![no_main="0400"] }
+    |                 ^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+    |
+791 |     #[no_main = "0400"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+    |
+791 |     #[no_main = "0400"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+    |
+795 |     #[no_main = "0400"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5
+    |
+795 |     #[no_main = "0400"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+    |
+799 |     #[no_main = "0400"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:5
+    |
+799 |     #[no_main = "0400"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+    |
+803 |     #[no_main = "0400"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:803:5
+    |
+803 |     #[no_main = "0400"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+    |
+783 | #[no_main = "0400"]
+    | ^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:1
+    |
+783 | #[no_main = "0400"]
+    | ^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+    |
+825 |     mod inner { #![recursion_limit="0200"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
+    |
+825 |     mod inner { #![recursion_limit="0200"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+    |
+829 |     #[recursion_limit="0200"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+    |
+829 |     #[recursion_limit="0200"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+    |
+833 |     #[recursion_limit="0200"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
+    |
+833 |     #[recursion_limit="0200"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+    |
+837 |     #[recursion_limit="0200"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:5
+    |
+837 |     #[recursion_limit="0200"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+    |
+841 |     #[recursion_limit="0200"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:841:5
+    |
+841 |     #[recursion_limit="0200"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+    |
+821 | #[recursion_limit="0200"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
+    |
+821 | #[recursion_limit="0200"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+    |
+850 |     mod inner { #![type_length_limit="0100"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be in the root module
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:17
+    |
+850 |     mod inner { #![type_length_limit="0100"] }
+    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+    |
+854 |     #[type_length_limit="0100"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5
+    |
+854 |     #[type_length_limit="0100"] fn f() { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+    |
+858 |     #[type_length_limit="0100"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5
+    |
+858 |     #[type_length_limit="0100"] struct S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+    |
+862 |     #[type_length_limit="0100"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5
+    |
+862 |     #[type_length_limit="0100"] type T = S;
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+    |
+866 |     #[type_length_limit="0100"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:866:5
+    |
+866 |     #[type_length_limit="0100"] impl S { }
+    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+    |
+846 | #[type_length_limit="0100"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:1
+    |
+846 | #[type_length_limit="0100"]
+    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
+   |
+53 | #![macro_reexport             = "5000"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1
+   |
+55 | #![macro_export               = "4800"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1
+   |
+56 | #![plugin_registrar           = "4700"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1
+   |
+59 | #![main                      = "x4400"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
+   |
+60 | #![start                     = "x4300"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1
+   |
+63 | #![simd                       = "4000"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
+   |
+64 | #![repr                       = "3900"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1
+   |
+65 | #![path                       = "3800"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
+   |
+66 | #![abi                        = "3700"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1
+   |
+67 | #![automatically_derived      = "3600"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
+   |
+69 | #![no_link                    = "3400"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1
+   |
+71 | #![should_panic               = "3200"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
+   |
+72 | #![ignore                     = "3100"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1
+   |
+78 | #![proc_macro_derive          = "2500"] //~ WARN unused attribute
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: compilation successful
+   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:1
+    |
+877 | / fn main() { //~ ERROR compilation successful
+878 | |     println!("Hello World");
+879 | | }
+    | |_^
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs
index 98da43c3a22..98da43c3a22 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-deprecated.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr
new file mode 100644
index 00000000000..a413fcc56a0
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr
@@ -0,0 +1,8 @@
+error: compilation successful
+  --> $DIR/issue-43106-gating-of-deprecated.rs:29:1
+   |
+29 | / fn main() { //~ ERROR compilation successful
+30 | |     println!("Hello World");
+31 | | }
+   | |_^
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
index 2dbc6cb140d..2dbc6cb140d 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
new file mode 100644
index 00000000000..c5b33384b91
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.stderr
@@ -0,0 +1,20 @@
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:14:14
+   |
+14 |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:18:14
+   |
+18 |     #[derive(x3300)]
+   |              ^^^^^
+
+error: cannot find derive macro `x3300` in this scope
+  --> $DIR/issue-43106-gating-of-derive-2.rs:22:14
+   |
+22 |     #[derive(x3300)]
+   |              ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs
index e5293ebb94d..e5293ebb94d 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr
new file mode 100644
index 00000000000..a0b12585f3c
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.stderr
@@ -0,0 +1,38 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:14:1
+   |
+14 | #![derive(Debug)]
+   | ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]`
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:17:1
+   |
+17 | #[derive(Debug)]
+   | ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:20:17
+   |
+20 |     mod inner { #![derive(Debug)] }
+   |                 ^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug)]`
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:23:5
+   |
+23 |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:36:5
+   |
+36 |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43106-gating-of-derive.rs:40:5
+   |
+40 |     #[derive(Debug)]
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
index 24e77bf60a8..24e77bf60a8 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-inline.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
new file mode 100644
index 00000000000..92bda4d0446
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr
@@ -0,0 +1,43 @@
+error[E0518]: attribute should be applied to function
+  --> $DIR/issue-43106-gating-of-inline.rs:21:1
+   |
+21 |   #[inline = "2100"]
+   |   ^^^^^^^^^^^^^^^^^^
+22 |   //~^ ERROR attribute should be applied to function
+23 | / mod inline {
+24 | |     mod inner { #![inline="2100"] }
+25 | |     //~^ ERROR attribute should be applied to function
+26 | |
+...  |
+36 | |     //~^ ERROR attribute should be applied to function
+37 | | }
+   | |_- not a function
+
+error[E0518]: attribute should be applied to function
+  --> $DIR/issue-43106-gating-of-inline.rs:24:17
+   |
+24 |     mod inner { #![inline="2100"] }
+   |     ------------^^^^^^^^^^^^^^^^^-- not a function
+
+error[E0518]: attribute should be applied to function
+  --> $DIR/issue-43106-gating-of-inline.rs:29:5
+   |
+29 |     #[inline = "2100"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^ --------- not a function
+
+error[E0518]: attribute should be applied to function
+  --> $DIR/issue-43106-gating-of-inline.rs:32:5
+   |
+32 |     #[inline = "2100"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^ ----------- not a function
+
+error[E0518]: attribute should be applied to function
+  --> $DIR/issue-43106-gating-of-inline.rs:35:5
+   |
+35 |     #[inline = "2100"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^ ---------- not a function
+
+error[E0601]: main function not found
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_escape.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
index 3b2dbdefeba..3b2dbdefeba 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_escape.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
new file mode 100644
index 00000000000..60a9382bdb8
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_escape.stderr
@@ -0,0 +1,12 @@
+warning: macro_escape is a deprecated synonym for macro_use
+  --> $DIR/issue-43106-gating-of-macro_escape.rs:16:1
+   |
+16 | #![macro_escape]
+   | ^^^^^^^^^^^^^^^^
+   |
+   = help: consider an outer attribute, #[macro_use] mod ...
+
+error[E0601]: main function not found
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_use.rs b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
index cf5619da3c7..cf5619da3c7 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-macro_use.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
new file mode 100644
index 00000000000..2977384f62d
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-macro_use.stderr
@@ -0,0 +1,20 @@
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:16:1
+   |
+16 | #![macro_use                  = "4900"] //~ ERROR arguments to macro_use are not allowed here
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:18:1
+   |
+18 | #[macro_use = "2700"]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: arguments to macro_use are not allowed here
+  --> $DIR/issue-43106-gating-of-macro_use.rs:21:17
+   |
+21 |     mod inner { #![macro_use="2700"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-proc_macro_derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
index 133f70e0f3b..133f70e0f3b 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr
new file mode 100644
index 00000000000..a76f0219f7a
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-proc_macro_derive.stderr
@@ -0,0 +1,40 @@
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:20:1
+   |
+20 | #[proc_macro_derive = "2500"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:28:17
+   |
+28 |     mod inner { #![proc_macro_derive="2500"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:31:5
+   |
+31 |     #[proc_macro_derive = "2500"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:34:5
+   |
+34 |     #[proc_macro_derive = "2500"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:37:5
+   |
+37 |     #[proc_macro_derive = "2500"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+  --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:40:5
+   |
+40 |     #[proc_macro_derive = "2500"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0601]: main function not found
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-rustc_deprecated.rs b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
index 10c13986349..10c13986349 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
new file mode 100644
index 00000000000..6f6f587cb53
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-rustc_deprecated.stderr
@@ -0,0 +1,46 @@
+error[E0601]: main function not found
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:17:1
+   |
+17 | #![rustc_deprecated           = "1500"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:20:1
+   |
+20 | #[rustc_deprecated = "1500"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:23:17
+   |
+23 |     mod inner { #![rustc_deprecated="1500"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:26:5
+   |
+26 |     #[rustc_deprecated = "1500"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:29:5
+   |
+29 |     #[rustc_deprecated = "1500"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:32:5
+   |
+32 |     #[rustc_deprecated = "1500"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-rustc_deprecated.rs:35:5
+   |
+35 |     #[rustc_deprecated = "1500"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-stable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
index a6eaabf7a38..a6eaabf7a38 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-stable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
new file mode 100644
index 00000000000..59f0431c708
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-stable.stderr
@@ -0,0 +1,46 @@
+error[E0601]: main function not found
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:17:1
+   |
+17 | #![stable                     = "1300"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:20:1
+   |
+20 | #[stable = "1300"]
+   | ^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:23:17
+   |
+23 |     mod inner { #![stable="1300"] }
+   |                 ^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:26:5
+   |
+26 |     #[stable = "1300"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:29:5
+   |
+29 |     #[stable = "1300"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:32:5
+   |
+32 |     #[stable = "1300"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-stable.rs:35:5
+   |
+35 |     #[stable = "1300"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
index adcbfe77280..adcbfe77280 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-test.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
new file mode 100644
index 00000000000..f7d5473f443
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr
@@ -0,0 +1,4 @@
+error[E0601]: main function not found
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-unstable.rs b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
index ff0600deb19..ff0600deb19 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-unstable.rs
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.rs
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
new file mode 100644
index 00000000000..00cbc62ab47
--- /dev/null
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-unstable.stderr
@@ -0,0 +1,46 @@
+error[E0601]: main function not found
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:17:1
+   |
+17 | #![unstable                   = "1200"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:20:1
+   |
+20 | #[unstable = "1200"]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:23:17
+   |
+23 |     mod inner { #![unstable="1200"] }
+   |                 ^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:26:5
+   |
+26 |     #[unstable = "1200"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:29:5
+   |
+29 |     #[unstable = "1200"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:32:5
+   |
+32 |     #[unstable = "1200"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: stability attributes may not be used outside of the standard library
+  --> $DIR/issue-43106-gating-of-unstable.rs:35:5
+   |
+35 |     #[unstable = "1200"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs
new file mode 100644
index 00000000000..00a0c94d221
--- /dev/null
+++ b/src/test/ui/nll/capture-ref-in-struct.rs
@@ -0,0 +1,50 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Znll -Zborrowck=mir
+
+// Test that a structure which tries to store a pointer to `y` into
+// `p` (indirectly) fails to compile.
+
+#![feature(rustc_attrs)]
+
+struct SomeStruct<'a, 'b: 'a> {
+    p: &'a mut &'b i32,
+    y: &'b i32,
+}
+
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let closure = SomeStruct {
+            p: &mut p,
+            y: &y,
+        };
+
+        closure.invoke();
+    }
+    //~^ ERROR borrowed value does not live long enough [E0597]
+
+    deref(p);
+}
+
+impl<'a, 'b> SomeStruct<'a, 'b> {
+    fn invoke(self) {
+        *self.p = self.y;
+    }
+}
+
+fn deref(_: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr
new file mode 100644
index 00000000000..f10e52e05f1
--- /dev/null
+++ b/src/test/ui/nll/capture-ref-in-struct.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/capture-ref-in-struct.rs:36:6
+   |
+28 |         let y = 22;
+   |             - temporary value created here
+...
+36 |     }
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs
new file mode 100644
index 00000000000..1e34aaf1ea0
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs
@@ -0,0 +1,53 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test closure that:
+//
+// - takes an argument `y` with lifetime `'a` (in the code, it's anonymous)
+// - stores `y` into another, longer-lived spot with lifetime `'b`
+//
+// Because `'a` and `'b` are two different, unrelated higher-ranked
+// regions with no relationship to one another, this is an error. This
+// error is reported by the closure itself and is not propagated to
+// its creator: this is because `'a` and `'b` are higher-ranked
+// (late-bound) regions and the closure is not allowed to propagate
+// additional where clauses between higher-ranked regions, only those
+// that appear free in its type (hence, we see it before the closure's
+// "external requirements" report).
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        //~^ ERROR free region `'_#4r` does not outlive free region `'_#3r`
+        //~| WARNING not reporting region error due to -Znll
+        closure(&mut p, &y);
+    }
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: FnMut(&mut &i32, &i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
new file mode 100644
index 00000000000..c842d51a2ad
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -0,0 +1,40 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/escape-argument-callee.rs:36:50
+   |
+36 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                                  ^
+
+error: free region `'_#4r` does not outlive free region `'_#3r`
+  --> $DIR/escape-argument-callee.rs:36:45
+   |
+36 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                             ^^^^^^
+
+note: External requirements
+  --> $DIR/escape-argument-callee.rs:36:38
+   |
+36 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) i32))
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/escape-argument-callee.rs:30:1
+   |
+30 | / fn test() {
+31 | |     let x = 44;
+32 | |     let mut p = &x;
+33 | |
+...  |
+42 | |     deref(p);
+43 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument_callee[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs
new file mode 100644
index 00000000000..1d8a916345e
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument.rs
@@ -0,0 +1,52 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test closure that:
+//
+// - takes an argument `y`
+// - stores `y` into another, longer-lived spot
+//
+// but is invoked with a spot that doesn't live long
+// enough to store `y`.
+//
+// The error is reported in the caller: invoking the closure links the
+// lifetime of the variable that is given as `y` (via subtyping) and
+// thus forces the corresponding borrow to live too long. This is
+// basically checking that the MIR type checker correctly enforces the
+// closure signature.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = expect_sig(|p, y| *p = y);
+        closure(&mut p, &y);
+    }
+    //~^ ERROR borrowed value does not live long enough [E0597]
+
+    deref(p);
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a, 'b> FnMut(&'a mut &'b i32, &'b i32)
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
new file mode 100644
index 00000000000..e5c7139573e
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -0,0 +1,39 @@
+note: External requirements
+  --> $DIR/escape-argument.rs:36:38
+   |
+36 |         let mut closure = expect_sig(|p, y| *p = y);
+   |                                      ^^^^^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_argument[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32))
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/escape-argument.rs:30:1
+   |
+30 | / fn test() {
+31 | |     let x = 44;
+32 | |     let mut p = &x;
+33 | |
+...  |
+41 | |     deref(p);
+42 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_argument[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-argument.rs:38:6
+   |
+35 |         let y = 22;
+   |             - temporary value created here
+...
+38 |     }
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
new file mode 100644
index 00000000000..9f4585bfbab
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs
@@ -0,0 +1,43 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// As in `escape-upvar-ref.rs`, test closure that:
+//
+// - captures a variable `y`
+// - stores reference to `y` into another, longer-lived spot
+//
+// except that the closure does so via a second closure.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+
+        let mut closure = || {
+            let mut closure1 = || p = &y;
+            closure1();
+        };
+
+        closure();
+    } //~ ERROR borrowed value does not live long enough
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
new file mode 100644
index 00000000000..201590f01f3
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
@@ -0,0 +1,61 @@
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:31:32
+   |
+31 |             let mut closure1 = || p = &y;
+   |                                ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: External requirements
+  --> $DIR/escape-upvar-nested.rs:30:27
+   |
+30 |           let mut closure = || {
+   |  ___________________________^
+31 | |             let mut closure1 = || p = &y;
+32 | |             closure1();
+33 | |         };
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-nested.rs:23:1
+   |
+23 | / fn test() {
+24 | |     let x = 44;
+25 | |     let mut p = &x;
+26 | |
+...  |
+38 | |     deref(p);
+39 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-upvar-nested.rs:36:6
+   |
+28 |         let y = 22;
+   |             - temporary value created here
+...
+36 |     } //~ ERROR borrowed value does not live long enough
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
new file mode 100644
index 00000000000..548a5ae5969
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs
@@ -0,0 +1,42 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test closure that:
+//
+// - captures a variable `y` by reference
+// - stores that reference to `y` into another, longer-lived place (`p`)
+//
+// Both of these are upvars of reference type (the capture of `y` is
+// of type `&'a i32`, the capture of `p` is of type `&mut &'b
+// i32`). The closure thus computes a relationship between `'a` and
+// `'b`.  This relationship is propagated to the closure creator,
+// which reports an error.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    let x = 44;
+    let mut p = &x;
+
+    {
+        let y = 22;
+        let mut closure = || p = &y;
+        closure();
+    } //~ ERROR borrowed value does not live long enough
+
+    deref(p);
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
new file mode 100644
index 00000000000..47ba66ade65
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
@@ -0,0 +1,42 @@
+note: External requirements
+  --> $DIR/escape-upvar-ref.rs:33:27
+   |
+33 |         let mut closure = || p = &y;
+   |                           ^^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               extern "rust-call" fn(()),
+               &'_#1r mut &'_#2r i32,
+               &'_#3r i32
+           ]
+   = note: number of external vids: 4
+   = note: where '_#3r: '_#2r
+
+note: No external requirements
+  --> $DIR/escape-upvar-ref.rs:27:1
+   |
+27 | / fn test() {
+28 | |     let x = 44;
+29 | |     let mut p = &x;
+30 | |
+...  |
+37 | |     deref(p);
+38 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs []
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/escape-upvar-ref.rs:35:6
+   |
+32 |         let y = 22;
+   |             - temporary value created here
+...
+35 |     } //~ ERROR borrowed value does not live long enough
+   |      ^ temporary value dropped here while still borrowed
+   |
+   = note: consider using a `let` binding to increase its lifetime
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
new file mode 100644
index 00000000000..c2f071cc029
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs
@@ -0,0 +1,63 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test where we fail to approximate due to demanding a postdom
+// relationship between our upper bounds.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'x: 'b
+// 'c: 'y
+//
+// we have to prove that `'x: 'y`. We currently can only approximate
+// via a postdominator -- hence we fail to choose between `'a` and
+// `'b` here and report the error in the closure.
+fn establish_relationships<'a, 'b, 'c, F>(
+    _cell_a: Cell<&'a u32>,
+    _cell_b: Cell<&'b u32>,
+    _cell_c: Cell<&'c u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'b &'x u32>, // shows that 'x: 'b
+        Cell<&'y &'c u32>, // shows that 'c: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+    establish_relationships(
+        cell_a,
+        cell_b,
+        cell_c,
+        |_outlives1, _outlives2, _outlives3, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            //~^ WARN not reporting region error due to -Znll
+            demand_y(x, y, p)
+            //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r`
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
new file mode 100644
index 00000000000..d581622c4c6
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -0,0 +1,46 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21
+   |
+55 |             let p = x.get();
+   |                     ^^^^^^^
+
+error: free region `'_#5r` does not outlive free region `'_#6r`
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:57:25
+   |
+57 |             demand_y(x, y, p)
+   |                         ^
+
+note: External requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
+   |
+53 | /         |_outlives1, _outlives2, _outlives3, x, y| {
+54 | |             // Only works if 'x: 'y:
+55 | |             let p = x.get();
+56 | |             //~^ WARN not reporting region error due to -Znll
+57 | |             demand_y(x, y, p)
+58 | |             //~^ ERROR free region `'_#5r` does not outlive free region `'_#6r`
+59 | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+           ]
+   = note: number of external vids: 4
+
+note: No external requirements
+  --> $DIR/propagate-approximated-fail-no-postdom.rs:48:1
+   |
+48 | / fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell<&'c u32>) {
+49 | |     establish_relationships(
+50 | |         cell_a,
+51 | |         cell_b,
+...  |
+60 | |     );
+61 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
new file mode 100644
index 00000000000..76a0762461a
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -0,0 +1,64 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Rather convoluted setup where we infer a relationship between two
+// free regions in the closure signature (`'a` and `'b`) on the basis
+// of a relationship between two bound regions (`'x` and `'y`).
+//
+// The idea is that, thanks to invoking `demand_y`, `'x: 'y` must
+// hold, where `'x` and `'y` are bound regions. The closure can't
+// prove that directly, and because `'x` and `'y` are bound it cannot
+// ask the caller to prove it either. But it has bounds on `'x` and
+// `'y` in terms of `'a` and `'b`, and it can propagate a relationship
+// between `'a` and `'b` to the caller.
+//
+// Note: the use of `Cell` here is to introduce invariance. One less
+// variable.
+//
+// FIXME(#45827): The `supply` function *ought* to generate an error, but it
+// currently does not. This is I believe a shortcoming of the MIR type
+// checker: the closure inference is expressing the correct
+// requirement, as you can see from the `#[rustc_regions]` output.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
new file mode 100644
index 00000000000..7553ac5b0c3
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-ref.rs:60:9
+   |
+60 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-ref.rs:58:47
+   |
+58 |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+59 | |         // Only works if 'x: 'y:
+60 | |         demand_y(x, y, x.get())
+61 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_ref[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-ref.rs:57:1
+   |
+57 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+58 | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+59 | |         // Only works if 'x: 'y:
+60 | |         demand_y(x, y, x.get())
+61 | |     });
+62 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
new file mode 100644
index 00000000000..0a47ee80256
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs
@@ -0,0 +1,53 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where we setup relationships like `'x: 'a` or `'a: 'x`,
+// where `'x` is bound in closure type but `'a` is free. This forces
+// us to approximate `'x` one way or the other.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+fn foo<'a, F>(_cell: Cell<&'a u32>, _f: F)
+where
+    F: for<'x> FnOnce(Cell<&'a u32>, Cell<&'x u32>),
+{
+}
+
+#[rustc_regions]
+fn case1() {
+    let a = 0;
+    let cell = Cell::new(&a);
+    foo(cell, |cell_a, cell_x| {
+        //~^ WARNING not reporting region error due to -Znll
+        cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+        //~^ ERROR free region `'_#2r` does not outlive free region `'_#1r`
+    })
+}
+
+#[rustc_regions]
+fn case2() {
+    let a = 0;
+    let cell = Cell::new(&a);
+
+    // As you can see in the stderr output, this closure propoagates a
+    // requirement that `'a: 'static'.
+    //
+    // FIXME(#45827) However, because of shortcomings in the MIR type
+    // checker, this does not result in errors later on (yet).
+    foo(cell, |cell_a, cell_x| {
+        cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
+    })
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
new file mode 100644
index 00000000000..e2de72ffe93
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -0,0 +1,75 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:5
+   |
+31 |     foo(cell, |cell_a, cell_x| {
+   |     ^^^
+
+error: free region `'_#2r` does not outlive free region `'_#1r`
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
+   |
+33 |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+   |         ^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15
+   |
+31 |       foo(cell, |cell_a, cell_x| {
+   |  _______________^
+32 | |         //~^ WARNING not reporting region error due to -Znll
+33 | |         cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
+34 | |         //~^ ERROR free region `'_#2r` does not outlive free region `'_#1r`
+35 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:12 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]::{{closure}}[0]) with closure substs [
+               i32,
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+           ]
+   = note: number of external vids: 2
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1
+   |
+28 | / fn case1() {
+29 | |     let a = 0;
+30 | |     let cell = Cell::new(&a);
+31 | |     foo(cell, |cell_a, cell_x| {
+...  |
+35 | |     })
+36 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:5 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case1[0]) with substs []
+
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:48:15
+   |
+48 |       foo(cell, |cell_a, cell_x| {
+   |  _______________^
+49 | |         cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
+50 | |     })
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:13 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]::{{closure}}[0]) with closure substs [
+               i32,
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
+           ]
+   = note: number of external vids: 2
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:39:1
+   |
+39 | / fn case2() {
+40 | |     let a = 0;
+41 | |     let cell = Cell::new(&a);
+42 | |
+...  |
+50 | |     })
+51 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_comparing_against_free[317d]::case2[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
new file mode 100644
index 00000000000..f776ddc8b15
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs
@@ -0,0 +1,51 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where we are trying to prove `'x: 'y` and are forced to
+// approximate the shorter end-point (`'y`) to with `'static`. This is
+// because `'y` is higher-ranked but we know of no relations to other
+// regions. Note that `'static` shows up in the stderr output as `'0`.
+//
+// FIXME(#45827) Because of shortcomings in the MIR type checker,
+// these errors are not (yet) reported.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+//
+// so the only way we can ensure that `'x: 'y` is to show that
+// `'a: 'static`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
new file mode 100644
index 00000000000..8d1b9a94ea6
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:47:9
+   |
+47 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47
+   |
+45 |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+46 | |         // Only works if 'x: 'y:
+47 | |         demand_y(x, y, x.get())
+48 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) u32>))
+           ]
+   = note: number of external vids: 2
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1
+   |
+44 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+45 | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+46 | |         // Only works if 'x: 'y:
+47 | |         demand_y(x, y, x.get())
+48 | |     });
+49 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
new file mode 100644
index 00000000000..54b501c9ab6
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs
@@ -0,0 +1,54 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where we are trying to prove `'x: 'y` and are forced to
+// approximate the shorter end-point (`'y`) to with `'static`. This is
+// because `'y` is higher-ranked but we know of only irrelevant
+// relations to other regions. Note that `'static` shows up in the
+// stderr output as `'0`.
+//
+// FIXME(#45827) Because of shortcomings in the MIR type checker,
+// these errors are not (yet) reported.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'y: 'b
+//
+// so the only way we can ensure that `'x: 'y` is to show that
+// `'a: 'static`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'a &'x u32>, // shows that 'x: 'a
+        &Cell<&'b &'y u32>, // shows that 'y: 'b
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
new file mode 100644
index 00000000000..9d318a63d8f
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:50:9
+   |
+50 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47
+   |
+48 |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+49 | |         // Only works if 'x: 'y:
+50 | |         demand_y(x, y, x.get())
+51 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#0r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1
+   |
+47 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+48 | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+49 | |         // Only works if 'x: 'y:
+50 | |         demand_y(x, y, x.get())
+51 | |     });
+52 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
new file mode 100644
index 00000000000..48d446b00af
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -0,0 +1,52 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A simpler variant of `outlives-from-argument` where cells are
+// passed by value.
+//
+// This is simpler because there are no "extraneous" region
+// relationships. In the 'main' variant, there are a number of
+// anonymous regions as well.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'x: 'a
+// 'b: 'y
+//
+// so if we are going to ensure that `'x: 'y`, then `'a: 'b` must
+// hold.
+fn establish_relationships<'a, 'b, F>(_cell_a: Cell<&'a u32>, _cell_b: Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'b u32>, // shows that 'b: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(outlives1, outlives2, x.get())
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
new file mode 100644
index 00000000000..ae5ad6f4b96
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -0,0 +1,36 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-approximated-val.rs:48:9
+   |
+48 |         demand_y(outlives1, outlives2, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-approximated-val.rs:46:45
+   |
+46 |       establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+   |  _____________________________________________^
+47 | |         // Only works if 'x: 'y:
+48 | |         demand_y(outlives1, outlives2, x.get())
+49 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_approximated_val[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-approximated-val.rs:45:1
+   |
+45 | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+46 | |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
+47 | |         // Only works if 'x: 'y:
+48 | |         demand_y(outlives1, outlives2, x.get())
+49 | |     });
+50 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
+
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
new file mode 100644
index 00000000000..a28b5f4c0f9
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs
@@ -0,0 +1,59 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test where we might in theory be able to see that the relationship
+// between two bound regions is true within closure and hence have no
+// need to propagate; but in fact we do because identity of free
+// regions is erased.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// In theory, callee knows that:
+//
+// 'x: 'a
+// 'a: 'y
+//
+// and hence could satisfy that `'x: 'y` locally. However, in our
+// checking, we ignore the precise free regions that come into the
+// region and just assign each position a distinct universally bound
+// region. Hence, we propagate a constraint to our caller that will
+// wind up being solvable.
+fn establish_relationships<'a, F>(
+    _cell_a: Cell<&'a u32>,
+    _closure: F,
+) where
+    F: for<'x, 'y> FnMut(
+        Cell<&'a &'x u32>, // shows that 'x: 'a
+        Cell<&'y &'a u32>, // shows that 'a: 'y
+        Cell<&'x u32>,
+        Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: Cell<&'x u32>, _cell_y: Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a>(cell_a: Cell<&'a u32>) {
+    establish_relationships(
+        cell_a,
+        |_outlives1, _outlives2, x, y| {
+            // Only works if 'x: 'y:
+            let p = x.get();
+            demand_y(x, y, p)
+        },
+    );
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
new file mode 100644
index 00000000000..64f3bb08c62
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -0,0 +1,37 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-despite-same-free-region.rs:53:21
+   |
+53 |             let p = x.get();
+   |                     ^^^^^^^
+
+note: External requirements
+  --> $DIR/propagate-despite-same-free-region.rs:51:9
+   |
+51 | /         |_outlives1, _outlives2, x, y| {
+52 | |             // Only works if 'x: 'y:
+53 | |             let p = x.get();
+54 | |             demand_y(x, y, p)
+55 | |         },
+   | |_________^
+   |
+   = note: defining type: DefId(0/1:16 ~ propagate_despite_same_free_region[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+           ]
+   = note: number of external vids: 3
+   = note: where '_#1r: '_#2r
+
+note: No external requirements
+  --> $DIR/propagate-despite-same-free-region.rs:48:1
+   |
+48 | / fn supply<'a>(cell_a: Cell<&'a u32>) {
+49 | |     establish_relationships(
+50 | |         cell_a,
+51 | |         |_outlives1, _outlives2, x, y| {
+...  |
+56 | |     );
+57 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_despite_same_free_region[317d]::supply[0]) with substs []
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
new file mode 100644
index 00000000000..4bbdcc44944
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs
@@ -0,0 +1,53 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Similarly to escape-argument-callee, a test case where the closure
+// requires a relationship between 2 unrelated higher-ranked regions,
+// with no helpful relations between the HRRs and free regions.
+//
+// In this case, the error is reported by the closure itself. This is
+// because it is unable to approximate the higher-ranked region `'x`,
+// as it knows of no relationships between `'x` and any
+// non-higher-ranked regions.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'b: 'y
+//
+// but this doesn't really help us in proving that `'x: 'y`, so closure gets an error.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#6r` does not outlive free region `'_#4r`
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
new file mode 100644
index 00000000000..6094f9aad81
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -0,0 +1,46 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
+   |
+47 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: free region `'_#6r` does not outlive free region `'_#4r`
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:21
+   |
+47 |         demand_y(x, y, x.get())
+   |                     ^
+
+note: External requirements
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47
+   |
+45 |       establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+   |  _______________________________________________^
+46 | |         // Only works if 'x: 'y:
+47 | |         demand_y(x, y, x.get())
+48 | |         //~^ WARN not reporting region error due to -Znll
+49 | |         //~| ERROR free region `'_#6r` does not outlive free region `'_#4r`
+50 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>))
+           ]
+   = note: number of external vids: 2
+
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:44:1
+   |
+44 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+45 | |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
+46 | |         // Only works if 'x: 'y:
+47 | |         demand_y(x, y, x.get())
+...  |
+50 | |     });
+51 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
new file mode 100644
index 00000000000..69fad354792
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs
@@ -0,0 +1,57 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Similarly to escape-argument-callee, a test case where the closure
+// requires a relationship between 2 unrelated higher-ranked regions,
+// with no helpful relations between the HRRs and free regions.
+//
+// In this case, the error is reported by the closure itself. This is
+// because it is unable to approximate the higher-ranked region `'x`,
+// as it only knows of regions that `'x` is outlived by, and none that
+// `'x` outlives.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Callee knows that:
+//
+// 'a: 'x
+// 'b: 'y
+//
+// but this doesn't really help us in proving that `'x: 'y`, so
+// closure gets an error.  In particular, we would need to know that
+// `'x: 'a`, so that we could approximate `'x` "downwards" to `'a`.
+fn establish_relationships<'a, 'b, F>(_cell_a: &Cell<&'a u32>, _cell_b: &Cell<&'b u32>, _closure: F)
+where
+    F: for<'x, 'y> FnMut(
+        &Cell<&'x &'a u32>, // shows that 'a: 'x
+        &Cell<&'y &'b u32>, // shows that 'b: 'y
+        &Cell<&'x u32>,
+        &Cell<&'y u32>,
+    ),
+{
+}
+
+fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u32) {}
+
+#[rustc_regions]
+fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+    establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+        // Only works if 'x: 'y:
+        demand_y(x, y, x.get())
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#5r` does not outlive free region `'_#7r`
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
new file mode 100644
index 00000000000..6658ee63abd
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -0,0 +1,46 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
+   |
+51 |         demand_y(x, y, x.get())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: free region `'_#5r` does not outlive free region `'_#7r`
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:21
+   |
+51 |         demand_y(x, y, x.get())
+   |                     ^
+
+note: External requirements
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47
+   |
+49 |       establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+   |  _______________________________________________^
+50 | |         // Only works if 'x: 'y:
+51 | |         demand_y(x, y, x.get())
+52 | |         //~^ WARN not reporting region error due to -Znll
+53 | |         //~| ERROR free region `'_#5r` does not outlive free region `'_#7r`
+54 | |     });
+   | |_____^
+   |
+   = note: defining type: DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
+           ]
+   = note: number of external vids: 3
+
+note: No external requirements
+  --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:48:1
+   |
+48 | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
+49 | |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
+50 | |         // Only works if 'x: 'y:
+51 | |         demand_y(x, y, x.get())
+...  |
+54 | |     });
+55 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:6 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
new file mode 100644
index 00000000000..c61cf8a940f
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+fn foo(x: &u32) -> &'static u32 {
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#1r` does not outlive free region `ReStatic`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
new file mode 100644
index 00000000000..ef7ea923912
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: free region `'_#1r` does not outlive free region `ReStatic`
+  --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
new file mode 100644
index 00000000000..fcda5c5420b
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Basic test for free regions in the NLL code. This test ought to
+// report an error due to a reborrowing constraint. Right now, we get
+// a variety of errors from the older, AST-based machinery (notably
+// borrowck), and then we get the NLL error at the end.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+fn foo<'a>(x: &'a u32) -> &'static u32 {
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#1r` does not outlive free region `ReStatic`
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
new file mode 100644
index 00000000000..6dcb8e7cf12
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: free region `'_#1r` does not outlive free region `ReStatic`
+  --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/named-region-basic.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
index 001ce41c277..c1e4dee0065 100644
--- a/src/test/ui/nll/named-region-basic.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
@@ -13,12 +13,12 @@
 // a variety of errors from the older, AST-based machinery (notably
 // borrowck), and then we get the NLL error at the end.
 
-// compile-flags:-Znll
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
 
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
-    &*x //~ ERROR free region `'a` does not outlive `'b`
-    //~^ ERROR `*x` does not live long enough
-    //~| WARN not reporting region error due to -Znll
+    &*x
+        //~^ WARN not reporting region error due to -Znll
+        //~| ERROR free region `'_#1r` does not outlive free region `'_#2r`
 }
 
 fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
new file mode 100644
index 00000000000..c1b2f440309
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
@@ -0,0 +1,14 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: free region `'_#1r` does not outlive free region `'_#2r`
+  --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/feature-gate-abi-sysv64.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
index 2a4aae8c06b..ffb1935e75e 100644
--- a/src/test/compile-fail/feature-gate-abi-sysv64.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs
@@ -8,12 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that the sysv64 ABI cannot be used when abi-sysv64 feature
-// gate is not used.
+// Basic test for free regions in the NLL code. This test does not
+// report an error because of the (implied) bound that `'b: 'a`.
 
-extern "sysv64" fn foo() {}
-//~^ ERROR sysv64 ABI is experimental and subject to change
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+// must-compile-successfully
 
-fn main() {
-    foo();
+#![allow(warnings)]
+
+fn foo<'a, 'b>(x: &'a &'b u32) -> &'a u32 {
+    &**x
 }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
new file mode 100644
index 00000000000..9314bbf9432
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test closure that takes two references and is supposed to return
+// the first, but actually returns the second. This should fail within
+// the closure.
+
+// compile-flags:-Znll -Zborrowck=mir -Zverbose
+
+#![feature(rustc_attrs)]
+
+#[rustc_regions]
+fn test() {
+    expect_sig(|a, b| b); // ought to return `a`
+    //~^ WARN not reporting region error due to -Znll
+    //~| ERROR free region `'_#3r` does not outlive free region `'_#2r`
+}
+
+fn expect_sig<F>(f: F) -> F
+    where F: for<'a> FnMut(&'a i32, &i32) -> &'a i32
+{
+    f
+}
+
+fn deref(_p: &i32) { }
+
+fn main() { }
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
new file mode 100644
index 00000000000..8999f69e8de
--- /dev/null
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -0,0 +1,38 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/return-wrong-bound-region.rs:21:23
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                       ^
+
+error: free region `'_#3r` does not outlive free region `'_#2r`
+  --> $DIR/return-wrong-bound-region.rs:21:23
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                       ^
+
+note: External requirements
+  --> $DIR/return-wrong-bound-region.rs:21:16
+   |
+21 |     expect_sig(|a, b| b); // ought to return `a`
+   |                ^^^^^^^^
+   |
+   = note: defining type: DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]) with closure substs [
+               i16,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex { depth: 1 }, BrNamed(crate0:DefIndex(0:0), 'r)) i32
+           ]
+   = note: number of external vids: 1
+
+note: No external requirements
+  --> $DIR/return-wrong-bound-region.rs:20:1
+   |
+20 | / fn test() {
+21 | |     expect_sig(|a, b| b); // ought to return `a`
+22 | |     //~^ WARN not reporting region error due to -Znll
+23 | |     //~| ERROR free region `'_#3r` does not outlive free region `'_#2r`
+24 | | }
+   | |_^
+   |
+   = note: defining type: DefId(0/0:3 ~ return_wrong_bound_region[317d]::test[0]) with substs []
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/named-region-basic.stderr b/src/test/ui/nll/named-region-basic.stderr
deleted file mode 100644
index 9c1de6c366c..00000000000
--- a/src/test/ui/nll/named-region-basic.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: not reporting region error due to -Znll
-  --> $DIR/named-region-basic.rs:19:5
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |     ^^^
-
-error[E0597]: `*x` does not live long enough
-  --> $DIR/named-region-basic.rs:19:6
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |      ^^ does not live long enough
-   |
-   = note: borrowed value must be valid for the static lifetime...
-note: ...but borrowed value is only valid for the lifetime 'a as defined on the function body at 18:1
-  --> $DIR/named-region-basic.rs:18:1
-   |
-18 | / fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
-19 | |     &*x //~ ERROR free region `'a` does not outlive `'b`
-20 | |     //~^ ERROR `*x` does not live long enough
-21 | |     //~| WARN not reporting region error due to -Znll
-22 | | }
-   | |_^
-
-error: free region `'a` does not outlive `'b`
-  --> $DIR/named-region-basic.rs:19:5
-   |
-19 |     &*x //~ ERROR free region `'a` does not outlive `'b`
-   |     ^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs b/src/test/ui/specialization-feature-gate-default.rs
index 3a01ecdf9db..3a01ecdf9db 100644
--- a/src/test/compile-fail/specialization/specialization-feature-gate-default.rs
+++ b/src/test/ui/specialization-feature-gate-default.rs
diff --git a/src/test/ui/specialization-feature-gate-default.stderr b/src/test/ui/specialization-feature-gate-default.stderr
new file mode 100644
index 00000000000..e17d1308385
--- /dev/null
+++ b/src/test/ui/specialization-feature-gate-default.stderr
@@ -0,0 +1,10 @@
+error: specialization is unstable (see issue #31844)
+  --> $DIR/specialization-feature-gate-default.rs:20:5
+   |
+20 |     default fn foo(&self) {} //~ ERROR specialization is unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(specialization)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs b/src/test/ui/specialization-feature-gate-overlap.rs
index 5eb48eab15e..5eb48eab15e 100644
--- a/src/test/compile-fail/specialization/specialization-feature-gate-overlap.rs
+++ b/src/test/ui/specialization-feature-gate-overlap.rs
diff --git a/src/test/ui/specialization-feature-gate-overlap.stderr b/src/test/ui/specialization-feature-gate-overlap.stderr
new file mode 100644
index 00000000000..7fe2891c908
--- /dev/null
+++ b/src/test/ui/specialization-feature-gate-overlap.stderr
@@ -0,0 +1,15 @@
+error[E0119]: conflicting implementations of trait `Foo` for type `u8`:
+  --> $DIR/specialization-feature-gate-overlap.rs:23:1
+   |
+19 | / impl<T> Foo for T {
+20 | |     fn foo(&self) {}
+21 | | }
+   | |_- first implementation here
+22 | 
+23 | / impl Foo for u8 { //~ ERROR E0119
+24 | |     fn foo(&self) {}
+25 | | }
+   | |_^ conflicting implementation for `u8`
+
+error: aborting due to previous error
+
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 660462ad419..48c3c5c8198 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -13,7 +13,7 @@ use std::fmt;
 use std::str::FromStr;
 use std::path::PathBuf;
 
-use test::ColorConfig;
+use test::{ColorConfig, TestPaths};
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum Mode {
@@ -221,3 +221,17 @@ pub struct Config {
     pub llvm_cxxflags: String,
     pub nodejs: Option<String>,
 }
+
+/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
+pub fn expected_output_path(testpaths: &TestPaths, revision: Option<&str>, kind: &str) -> PathBuf {
+    assert!(UI_EXTENSIONS.contains(&kind));
+    let extension = match revision {
+        Some(r) => format!("{}.{}", r, kind),
+        None => kind.to_string(),
+    };
+    testpaths.file.with_extension(extension)
+}
+
+pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT];
+pub const UI_STDERR: &str = "stderr";
+pub const UI_STDOUT: &str = "stdout";
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index c853d53829c..e7851c36327 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -26,6 +26,7 @@ pub struct EarlyProps {
     pub ignore: bool,
     pub should_fail: bool,
     pub aux: Vec<String>,
+    pub revisions: Vec<String>,
 }
 
 impl EarlyProps {
@@ -34,6 +35,7 @@ impl EarlyProps {
             ignore: false,
             should_fail: false,
             aux: Vec::new(),
+            revisions: vec![],
         };
 
         iter_header(testfile,
@@ -50,6 +52,10 @@ impl EarlyProps {
                 props.aux.push(s);
             }
 
+            if let Some(r) = config.parse_revisions(ln) {
+                props.revisions.extend(r);
+            }
+
             props.should_fail = props.should_fail || config.parse_name_directive(ln, "should-fail");
         });
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 6da37df1927..fac3b71f82c 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -9,22 +9,20 @@
 // except according to those terms.
 
 #![crate_name = "compiletest"]
-
 #![feature(test)]
 #![feature(slice_rotate)]
-
 #![deny(warnings)]
 
+extern crate diff;
+extern crate env_logger;
+extern crate filetime;
+extern crate getopts;
 #[cfg(unix)]
 extern crate libc;
-extern crate test;
-extern crate getopts;
-extern crate rustc_serialize;
 #[macro_use]
 extern crate log;
-extern crate env_logger;
-extern crate filetime;
-extern crate diff;
+extern crate rustc_serialize;
+extern crate test;
 
 use std::env;
 use std::ffi::OsString;
@@ -35,8 +33,9 @@ use std::process::Command;
 use filetime::FileTime;
 use getopts::Options;
 use common::Config;
-use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode};
-use test::{TestPaths, ColorConfig};
+use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
+use common::{expected_output_path, UI_EXTENSIONS};
+use test::{ColorConfig, TestPaths};
 use util::logv;
 
 use self::header::EarlyProps;
@@ -63,53 +62,168 @@ fn main() {
     run_tests(&config);
 }
 
-pub fn parse_config(args: Vec<String> ) -> Config {
-
+pub fn parse_config(args: Vec<String>) -> Config {
     let mut opts = Options::new();
-    opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
-        .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
-        .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
-        .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
-        .reqopt("", "lldb-python", "path to python to use for doc tests", "PATH")
-        .reqopt("", "docck-python", "path to python to use for doc tests", "PATH")
-        .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM")
-        .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind")
-        .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
+    opts.reqopt(
+        "",
+        "compile-lib-path",
+        "path to host shared libraries",
+        "PATH",
+    ).reqopt(
+            "",
+            "run-lib-path",
+            "path to target shared libraries",
+            "PATH",
+        )
+        .reqopt(
+            "",
+            "rustc-path",
+            "path to rustc to use for compiling",
+            "PATH",
+        )
+        .optopt(
+            "",
+            "rustdoc-path",
+            "path to rustdoc to use for compiling",
+            "PATH",
+        )
+        .reqopt(
+            "",
+            "lldb-python",
+            "path to python to use for doc tests",
+            "PATH",
+        )
+        .reqopt(
+            "",
+            "docck-python",
+            "path to python to use for doc tests",
+            "PATH",
+        )
+        .optopt(
+            "",
+            "valgrind-path",
+            "path to Valgrind executable for Valgrind tests",
+            "PROGRAM",
+        )
+        .optflag(
+            "",
+            "force-valgrind",
+            "fail if Valgrind tests cannot be run under Valgrind",
+        )
+        .optopt(
+            "",
+            "llvm-filecheck",
+            "path to LLVM's FileCheck binary",
+            "DIR",
+        )
         .reqopt("", "src-base", "directory to scan for test files", "PATH")
-        .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
-        .reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET")
-        .reqopt("", "mode", "which sort of compile tests to run",
-                "(compile-fail|parse-fail|run-fail|run-pass|\
-                 run-pass-valgrind|pretty|debug-info|incremental|mir-opt)")
+        .reqopt(
+            "",
+            "build-base",
+            "directory to deposit test outputs",
+            "PATH",
+        )
+        .reqopt(
+            "",
+            "stage-id",
+            "the target-stage identifier",
+            "stageN-TARGET",
+        )
+        .reqopt(
+            "",
+            "mode",
+            "which sort of compile tests to run",
+            "(compile-fail|parse-fail|run-fail|run-pass|\
+             run-pass-valgrind|pretty|debug-info|incremental|mir-opt)",
+        )
         .optflag("", "ignored", "run tests marked as ignored")
         .optflag("", "exact", "filters match exactly")
-        .optopt("", "runtool", "supervisor program to run tests under \
-                                (eg. emulator, valgrind)", "PROGRAM")
-        .optopt("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
-        .optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
+        .optopt(
+            "",
+            "runtool",
+            "supervisor program to run tests under \
+             (eg. emulator, valgrind)",
+            "PROGRAM",
+        )
+        .optopt(
+            "",
+            "host-rustcflags",
+            "flags to pass to rustc for host",
+            "FLAGS",
+        )
+        .optopt(
+            "",
+            "target-rustcflags",
+            "flags to pass to rustc for target",
+            "FLAGS",
+        )
         .optflag("", "verbose", "run tests verbosely, showing all output")
-        .optflag("", "quiet", "print one character per test instead of one line")
+        .optflag(
+            "",
+            "quiet",
+            "print one character per test instead of one line",
+        )
         .optopt("", "color", "coloring: auto, always, never", "WHEN")
         .optopt("", "logfile", "file to log test execution to", "FILE")
         .optopt("", "target", "the target to build for", "TARGET")
         .optopt("", "host", "the host to build for", "HOST")
-        .optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH")
-        .optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING")
-        .optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING")
+        .optopt(
+            "",
+            "gdb",
+            "path to GDB to use for GDB debuginfo tests",
+            "PATH",
+        )
+        .optopt(
+            "",
+            "lldb-version",
+            "the version of LLDB used",
+            "VERSION STRING",
+        )
+        .optopt(
+            "",
+            "llvm-version",
+            "the version of LLVM used",
+            "VERSION STRING",
+        )
         .optflag("", "system-llvm", "is LLVM the system LLVM")
-        .optopt("", "android-cross-path", "Android NDK standalone path", "PATH")
+        .optopt(
+            "",
+            "android-cross-path",
+            "Android NDK standalone path",
+            "PATH",
+        )
         .optopt("", "adb-path", "path to the android debugger", "PATH")
-        .optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH")
-        .optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH")
+        .optopt(
+            "",
+            "adb-test-dir",
+            "path to tests for the android debugger",
+            "PATH",
+        )
+        .optopt(
+            "",
+            "lldb-python-dir",
+            "directory containing LLDB's python module",
+            "PATH",
+        )
         .reqopt("", "cc", "path to a C compiler", "PATH")
         .reqopt("", "cxx", "path to a C++ compiler", "PATH")
         .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
         .optopt("", "ar", "path to an archiver", "PATH")
         .optopt("", "linker", "path to a linker", "PATH")
-        .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
+        .reqopt(
+            "",
+            "llvm-components",
+            "list of LLVM components built in",
+            "LIST",
+        )
         .reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS")
         .optopt("", "nodejs", "the name of nodejs", "PATH")
-        .optopt("", "remote-test-client", "path to the remote test client", "PATH")
+        .optopt(
+            "",
+            "remote-test-client",
+            "path to the remote test client",
+            "PATH",
+        )
         .optflag("h", "help", "show this message");
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -120,11 +234,10 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         panic!()
     }
 
-    let matches =
-        &match opts.parse(args_) {
-          Ok(m) => m,
-          Err(f) => panic!("{:?}", f)
-        };
+    let matches = &match opts.parse(args_) {
+        Ok(m) => m,
+        Err(f) => panic!("{:?}", f),
+    };
 
     if matches.opt_present("h") || matches.opt_present("help") {
         let message = format!("Usage: {} [OPTIONS]  [TESTNAME...]", argv0);
@@ -154,7 +267,10 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         Some("auto") | None => ColorConfig::AutoColor,
         Some("always") => ColorConfig::AlwaysColor,
         Some("never") => ColorConfig::NeverColor,
-        Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
+        Some(x) => panic!(
+            "argument for --color must be auto, always, or never, but found `{}`",
+            x
+        ),
     };
 
     Config {
@@ -170,7 +286,11 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         src_base: opt_path(matches, "src-base"),
         build_base: opt_path(matches, "build-base"),
         stage_id: matches.opt_str("stage-id").unwrap(),
-        mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"),
+        mode: matches
+            .opt_str("mode")
+            .unwrap()
+            .parse()
+            .expect("invalid mode"),
         run_ignored: matches.opt_present("ignored"),
         filter: matches.free.first().cloned(),
         filter_exact: matches.opt_present("exact"),
@@ -189,10 +309,9 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         android_cross_path: opt_path(matches, "android-cross-path"),
         adb_path: opt_str2(matches.opt_str("adb-path")),
         adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")),
-        adb_device_status:
-            opt_str2(matches.opt_str("target")).contains("android") &&
-            "(none)" != opt_str2(matches.opt_str("adb-test-dir")) &&
-            !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
+        adb_device_status: opt_str2(matches.opt_str("target")).contains("android")
+            && "(none)" != opt_str2(matches.opt_str("adb-test-dir"))
+            && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
         lldb_python_dir: matches.opt_str("lldb-python-dir"),
         verbose: matches.opt_present("verbose"),
         quiet: matches.opt_present("quiet"),
@@ -213,7 +332,10 @@ pub fn parse_config(args: Vec<String> ) -> Config {
 pub fn log_config(config: &Config) {
     let c = config;
     logv(c, "configuration:".to_string());
-    logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
+    logv(
+        c,
+        format!("compile_lib_path: {:?}", config.compile_lib_path),
+    );
     logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
     logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
     logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
@@ -222,24 +344,38 @@ pub fn log_config(config: &Config) {
     logv(c, format!("stage_id: {}", config.stage_id));
     logv(c, format!("mode: {}", config.mode));
     logv(c, format!("run_ignored: {}", config.run_ignored));
-    logv(c, format!("filter: {}",
-                    opt_str(&config.filter
-                                   .as_ref()
-                                   .map(|re| re.to_owned()))));
+    logv(
+        c,
+        format!(
+            "filter: {}",
+            opt_str(&config.filter.as_ref().map(|re| re.to_owned()))
+        ),
+    );
     logv(c, format!("filter_exact: {}", config.filter_exact));
     logv(c, format!("runtool: {}", opt_str(&config.runtool)));
-    logv(c, format!("host-rustcflags: {}",
-                    opt_str(&config.host_rustcflags)));
-    logv(c, format!("target-rustcflags: {}",
-                    opt_str(&config.target_rustcflags)));
+    logv(
+        c,
+        format!("host-rustcflags: {}", opt_str(&config.host_rustcflags)),
+    );
+    logv(
+        c,
+        format!("target-rustcflags: {}", opt_str(&config.target_rustcflags)),
+    );
     logv(c, format!("target: {}", config.target));
     logv(c, format!("host: {}", config.host));
-    logv(c, format!("android-cross-path: {:?}",
-                    config.android_cross_path.display()));
+    logv(
+        c,
+        format!(
+            "android-cross-path: {:?}",
+            config.android_cross_path.display()
+        ),
+    );
     logv(c, format!("adb_path: {:?}", config.adb_path));
     logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
-    logv(c, format!("adb_device_status: {}",
-                    config.adb_device_status));
+    logv(
+        c,
+        format!("adb_device_status: {}", config.adb_device_status),
+    );
     logv(c, format!("ar: {}", config.ar));
     logv(c, format!("linker: {:?}", config.linker));
     logv(c, format!("verbose: {}", config.verbose));
@@ -264,8 +400,11 @@ pub fn opt_str2(maybestr: Option<String>) -> String {
 pub fn run_tests(config: &Config) {
     if config.target.contains("android") {
         if let DebugInfoGdb = config.mode {
-            println!("{} debug-info test uses tcp 5039 port.\
-                     please reserve it", config.target);
+            println!(
+                "{} debug-info test uses tcp 5039 port.\
+                 please reserve it",
+                config.target
+            );
 
             // android debug-info test uses remote debugger so, we test 1 thread
             // at once as they're all sharing the same TCP port to communicate
@@ -281,12 +420,14 @@ pub fn run_tests(config: &Config) {
         DebugInfoLldb => {
             if let Some(lldb_version) = config.lldb_version.as_ref() {
                 if is_blacklisted_lldb_version(&lldb_version[..]) {
-                    println!("WARNING: The used version of LLDB ({}) has a \
-                              known issue that breaks debuginfo tests. See \
-                              issue #32520 for more information. Skipping all \
-                              LLDB-based tests!",
-                             lldb_version);
-                    return
+                    println!(
+                        "WARNING: The used version of LLDB ({}) has a \
+                         known issue that breaks debuginfo tests. See \
+                         issue #32520 for more information. Skipping all \
+                         LLDB-based tests!",
+                        lldb_version
+                    );
+                    return;
                 }
             }
 
@@ -297,11 +438,12 @@ pub fn run_tests(config: &Config) {
         }
 
         DebugInfoGdb => {
-            if config.remote_test_client.is_some() &&
-               !config.target.contains("android"){
-                println!("WARNING: debuginfo tests are not available when \
-                          testing with remote");
-                return
+            if config.remote_test_client.is_some() && !config.target.contains("android") {
+                println!(
+                    "WARNING: debuginfo tests are not available when \
+                     testing with remote"
+                );
+                return;
             }
         }
         _ => { /* proceed */ }
@@ -317,7 +459,9 @@ pub fn run_tests(config: &Config) {
     // sadly osx needs some file descriptor limits raised for running tests in
     // parallel (especially when we have lots and lots of child processes).
     // For context, see #8904
-    unsafe { raise_fd_limit::raise_fd_limit(); }
+    unsafe {
+        raise_fd_limit::raise_fd_limit();
+    }
     // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
     // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
     env::set_var("__COMPAT_LAYER", "RunAsInvoker");
@@ -346,7 +490,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
         bench_benchmarks: true,
         nocapture: match env::var("RUST_TEST_NOCAPTURE") {
             Ok(val) => &val != "0",
-            Err(_) => false
+            Err(_) => false,
         },
         color: config.color,
         test_threads: None,
@@ -357,24 +501,25 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
 }
 
 pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
-    debug!("making tests from {:?}",
-           config.src_base.display());
+    debug!("making tests from {:?}", config.src_base.display());
     let mut tests = Vec::new();
-    collect_tests_from_dir(config,
-                           &config.src_base,
-                           &config.src_base,
-                           &PathBuf::new(),
-                           &mut tests)
-        .unwrap();
+    collect_tests_from_dir(
+        config,
+        &config.src_base,
+        &config.src_base,
+        &PathBuf::new(),
+        &mut tests,
+    ).unwrap();
     tests
 }
 
-fn collect_tests_from_dir(config: &Config,
-                          base: &Path,
-                          dir: &Path,
-                          relative_dir_path: &Path,
-                          tests: &mut Vec<test::TestDescAndFn>)
-                          -> io::Result<()> {
+fn collect_tests_from_dir(
+    config: &Config,
+    base: &Path,
+    dir: &Path,
+    relative_dir_path: &Path,
+    tests: &mut Vec<test::TestDescAndFn>,
+) -> io::Result<()> {
     // Ignore directories that contain a file
     // `compiletest-ignore-dir`.
     for file in fs::read_dir(dir)? {
@@ -390,7 +535,7 @@ fn collect_tests_from_dir(config: &Config,
                 relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
             };
             tests.push(make_test(config, &paths));
-            return Ok(())
+            return Ok(());
         }
     }
 
@@ -430,11 +575,7 @@ fn collect_tests_from_dir(config: &Config,
                 fs::create_dir_all(&build_dir).unwrap();
             } else {
                 debug!("found directory: {:?}", file_path.display());
-                collect_tests_from_dir(config,
-                                       base,
-                                       &file_path,
-                                       &relative_file_path,
-                                       tests)?;
+                collect_tests_from_dir(config, base, &file_path, &relative_file_path, tests)?;
             }
         } else {
             debug!("found other file/directory: {:?}", file_path.display());
@@ -467,13 +608,13 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
             test::ShouldPanic::Yes
         } else {
             test::ShouldPanic::No
-        }
+        },
     };
 
     // Debugging emscripten code doesn't make sense today
-    let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) ||
-                 (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) &&
-                  config.target.contains("emscripten");
+    let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props)
+        || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
+            && config.target.contains("emscripten");
 
     test::TestDescAndFn {
         desc: test::TestDesc {
@@ -487,28 +628,32 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
 }
 
 fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
-    let stamp_name = format!("{}-{}.stamp",
-                             testpaths.file.file_name().unwrap()
-                                           .to_str().unwrap(),
-                             config.stage_id);
-    config.build_base.canonicalize()
-          .unwrap_or_else(|_| config.build_base.clone())
-          .join(&testpaths.relative_dir)
-          .join(stamp_name)
+    let stamp_name = format!(
+        "{}-{}.stamp",
+        testpaths.file.file_name().unwrap().to_str().unwrap(),
+        config.stage_id
+    );
+    config
+        .build_base
+        .canonicalize()
+        .unwrap_or_else(|_| config.build_base.clone())
+        .join(&testpaths.relative_dir)
+        .join(stamp_name)
 }
 
 fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> bool {
-    let rust_src_dir = config.find_rust_src_root().expect(
-        "Could not find Rust source root",
-    );
+    let rust_src_dir = config
+        .find_rust_src_root()
+        .expect("Could not find Rust source root");
     let stamp = mtime(&stamp(config, testpaths));
     let mut inputs = vec![mtime(&testpaths.file), mtime(&config.rustc_path)];
     for aux in props.aux.iter() {
-        inputs.push(mtime(
-            &testpaths.file.parent().unwrap().join("auxiliary").join(
-                aux,
-            ),
-        ));
+        inputs.push(mtime(&testpaths
+            .file
+            .parent()
+            .unwrap()
+            .join("auxiliary")
+            .join(aux)));
     }
     // Relevant pretty printer files
     let pretty_printer_files = [
@@ -529,21 +674,34 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
         inputs.push(mtime(&rustdoc_path));
         inputs.push(mtime(&rust_src_dir.join("src/etc/htmldocck.py")));
     }
+
+    // UI test files.
+    for extension in UI_EXTENSIONS {
+        for revision in &props.revisions {
+            let path = &expected_output_path(testpaths, Some(revision), extension);
+            inputs.push(mtime(path));
+        }
+
+        if props.revisions.is_empty() {
+            let path = &expected_output_path(testpaths, None, extension);
+            inputs.push(mtime(path));
+        }
+    }
+
     inputs.iter().any(|input| *input > stamp)
 }
 
 fn mtime(path: &Path) -> FileTime {
-    fs::metadata(path).map(|f| {
-        FileTime::from_last_modification_time(&f)
-    }).unwrap_or_else(|_| FileTime::zero())
+    fs::metadata(path)
+        .map(|f| FileTime::from_last_modification_time(&f))
+        .unwrap_or_else(|_| FileTime::zero())
 }
 
 pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName {
     // Convert a complete path to something like
     //
     //    run-pass/foo/bar/baz.rs
-    let path =
-        PathBuf::from(config.src_base.file_name().unwrap())
+    let path = PathBuf::from(config.src_base.file_name().unwrap())
         .join(&testpaths.relative_dir)
         .join(&testpaths.file.file_name().unwrap());
     test::DynTestName(format!("[{}] {}", config.mode, path.display()))
@@ -552,9 +710,7 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName
 pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
     let config = config.clone();
     let testpaths = testpaths.clone();
-    test::DynTestFn(Box::new(move |()| {
-        runtest::run(config, &testpaths)
-    }))
+    test::DynTestFn(Box::new(move |()| runtest::run(config, &testpaths)))
 }
 
 /// Returns (Path to GDB, GDB Version, GDB has Rust Support)
@@ -572,9 +728,17 @@ fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) {
         Some(ref s) => s,
     };
 
-    let version_line = Command::new(gdb).arg("--version").output().map(|output| {
-        String::from_utf8_lossy(&output.stdout).lines().next().unwrap().to_string()
-    }).ok();
+    let version_line = Command::new(gdb)
+        .arg("--version")
+        .output()
+        .map(|output| {
+            String::from_utf8_lossy(&output.stdout)
+                .lines()
+                .next()
+                .unwrap()
+                .to_string()
+        })
+        .ok();
 
     let version = match version_line {
         Some(line) => extract_gdb_version(&line),
@@ -600,7 +764,7 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
     for (pos, c) in full_version_line.char_indices() {
         if prev_was_digit || !c.is_digit(10) {
             prev_was_digit = c.is_digit(10);
-            continue
+            continue;
         }
 
         prev_was_digit = true;
@@ -623,10 +787,15 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
             Some(idx) => if line.as_bytes()[idx] == b'.' {
                 let patch = &line[idx + 1..];
 
-                let patch_len = patch.find(|c: char| !c.is_digit(10))
-                                                       .unwrap_or_else(|| patch.len());
+                let patch_len = patch
+                    .find(|c: char| !c.is_digit(10))
+                    .unwrap_or_else(|| patch.len());
                 let patch = &patch[..patch_len];
-                let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) };
+                let patch = if patch_len > 3 || patch_len == 0 {
+                    None
+                } else {
+                    Some(patch)
+                };
 
                 (&line[..idx], patch)
             } else {
@@ -666,21 +835,36 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
             let full_version_line = full_version_line.trim();
 
             for (pos, l) in full_version_line.char_indices() {
-                if l != 'l' && l != 'L' { continue }
-                if pos + 5 >= full_version_line.len() { continue }
+                if l != 'l' && l != 'L' {
+                    continue;
+                }
+                if pos + 5 >= full_version_line.len() {
+                    continue;
+                }
                 let l = full_version_line[pos + 1..].chars().next().unwrap();
-                if l != 'l' && l != 'L' { continue }
+                if l != 'l' && l != 'L' {
+                    continue;
+                }
                 let d = full_version_line[pos + 2..].chars().next().unwrap();
-                if d != 'd' && d != 'D' { continue }
+                if d != 'd' && d != 'D' {
+                    continue;
+                }
                 let b = full_version_line[pos + 3..].chars().next().unwrap();
-                if b != 'b' && b != 'B' { continue }
+                if b != 'b' && b != 'B' {
+                    continue;
+                }
                 let dash = full_version_line[pos + 4..].chars().next().unwrap();
-                if dash != '-' { continue }
+                if dash != '-' {
+                    continue;
+                }
 
-                let vers = full_version_line[pos + 5..].chars().take_while(|c| {
-                    c.is_digit(10)
-                }).collect::<String>();
-                if !vers.is_empty() { return Some(vers) }
+                let vers = full_version_line[pos + 5..]
+                    .chars()
+                    .take_while(|c| c.is_digit(10))
+                    .collect::<String>();
+                if !vers.is_empty() {
+                    return Some(vers);
+                }
             }
         }
     }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7d20bb74c7a..a18f4ec1aad 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -10,10 +10,11 @@
 
 use common::Config;
 use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
-use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
-use common::{Incremental, RunMake, Ui, MirOpt};
+use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
+use common::{Incremental, MirOpt, RunMake, Ui};
+use common::{expected_output_path, UI_STDERR, UI_STDOUT};
 use diff;
-use errors::{self, ErrorKind, Error};
+use errors::{self, Error, ErrorKind};
 use filetime::FileTime;
 use json;
 use header::TestProps;
@@ -24,12 +25,12 @@ use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
 use std::ffi::OsString;
-use std::fs::{self, File, create_dir_all};
+use std::fs::{self, create_dir_all, File};
 use std::fmt;
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output, ExitStatus, Stdio, Child};
+use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::str;
 
 use extract_gdb_version;
@@ -49,7 +50,6 @@ pub fn dylib_env_var() -> &'static str {
 
 pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
-
         "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
             if !config.adb_device_status {
                 panic!("android device not available");
@@ -71,24 +71,24 @@ pub fn run(config: Config, testpaths: &TestPaths) {
     debug!("running {:?}", testpaths.file.display());
     let base_props = TestProps::from_file(&testpaths.file, None, &config);
 
-    let base_cx = TestCx { config: &config,
-                           props: &base_props,
-                           testpaths,
-                           revision: None };
+    let base_cx = TestCx {
+        config: &config,
+        props: &base_props,
+        testpaths,
+        revision: None,
+    };
     base_cx.init_all();
 
     if base_props.revisions.is_empty() {
         base_cx.run_revision()
     } else {
         for revision in &base_props.revisions {
-            let revision_props = TestProps::from_file(&testpaths.file,
-                                                      Some(revision),
-                                                      &config);
+            let revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config);
             let rev_cx = TestCx {
                 config: &config,
                 props: &revision_props,
                 testpaths,
-                revision: Some(revision)
+                revision: Some(revision),
             };
             rev_cx.run_revision();
         }
@@ -103,7 +103,7 @@ struct TestCx<'test> {
     config: &'test Config,
     props: &'test TestProps,
     testpaths: &'test TestPaths,
-    revision: Option<&'test str>
+    revision: Option<&'test str>,
 }
 
 struct DebuggerCommands {
@@ -125,8 +125,7 @@ impl<'test> TestCx<'test> {
     /// revisions, exactly once, with revision == None).
     fn run_revision(&self) {
         match self.config.mode {
-            CompileFail |
-            ParseFail => self.run_cfail_test(),
+            CompileFail | ParseFail => self.run_cfail_test(),
             RunFail => self.run_rfail_test(),
             RunPass => self.run_rpass_test(),
             RunPassValgrind => self.run_valgrind_test(),
@@ -153,15 +152,14 @@ impl<'test> TestCx<'test> {
 
         if self.props.must_compile_successfully {
             if !proc_res.status.success() {
-                self.fatal_proc_rec(
-                    "test compilation failed although it shouldn't!",
-                    &proc_res);
+                self.fatal_proc_rec("test compilation failed although it shouldn't!", &proc_res);
             }
         } else {
             if proc_res.status.success() {
                 self.fatal_proc_rec(
                     &format!("{} test compiled successfully!", self.config.mode)[..],
-                    &proc_res);
+                    &proc_res,
+                );
             }
 
             self.check_correct_failure_status(&proc_res);
@@ -215,9 +213,9 @@ impl<'test> TestCx<'test> {
         const RUST_ERR: i32 = 101;
         if proc_res.status.code() != Some(RUST_ERR) {
             self.fatal_proc_rec(
-                &format!("failure produced the wrong error: {}",
-                         proc_res.status),
-                proc_res);
+                &format!("failure produced the wrong error: {}", proc_res.status),
+                proc_res,
+            );
         }
     }
 
@@ -230,8 +228,10 @@ impl<'test> TestCx<'test> {
 
         // FIXME(#41968): Move this check to tidy?
         let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
-        assert!(expected_errors.is_empty(),
-                "run-pass tests with expected warnings should be moved to ui/");
+        assert!(
+            expected_errors.is_empty(),
+            "run-pass tests with expected warnings should be moved to ui/"
+        );
 
         let proc_res = self.exec_compiled_test();
 
@@ -256,7 +256,10 @@ impl<'test> TestCx<'test> {
 
         let mut new_config = self.config.clone();
         new_config.runtool = new_config.valgrind_path.clone();
-        let new_cx = TestCx { config: &new_config, ..*self };
+        let new_cx = TestCx {
+            config: &new_config,
+            ..*self
+        };
         proc_res = new_cx.exec_compiled_test();
 
         if !proc_res.status.success() {
@@ -268,28 +271,48 @@ impl<'test> TestCx<'test> {
         if self.props.pp_exact.is_some() {
             logv(self.config, "testing for exact pretty-printing".to_owned());
         } else {
-            logv(self.config, "testing for converging pretty-printing".to_owned());
+            logv(
+                self.config,
+                "testing for converging pretty-printing".to_owned(),
+            );
         }
 
-        let rounds = match self.props.pp_exact { Some(_) => 1, None => 2 };
+        let rounds = match self.props.pp_exact {
+            Some(_) => 1,
+            None => 2,
+        };
 
         let mut src = String::new();
-        File::open(&self.testpaths.file).unwrap().read_to_string(&mut src).unwrap();
+        File::open(&self.testpaths.file)
+            .unwrap()
+            .read_to_string(&mut src)
+            .unwrap();
         let mut srcs = vec![src];
 
         let mut round = 0;
         while round < rounds {
-            logv(self.config, format!("pretty-printing round {} revision {:?}",
-                                      round, self.revision));
+            logv(
+                self.config,
+                format!(
+                    "pretty-printing round {} revision {:?}",
+                    round,
+                    self.revision
+                ),
+            );
             let proc_res = self.print_source(srcs[round].to_owned(), &self.props.pretty_mode);
 
             if !proc_res.status.success() {
-                self.fatal_proc_rec(&format!("pretty-printing failed in round {} revision {:?}",
-                                             round, self.revision),
-                                    &proc_res);
+                self.fatal_proc_rec(
+                    &format!(
+                        "pretty-printing failed in round {} revision {:?}",
+                        round,
+                        self.revision
+                    ),
+                    &proc_res,
+                );
             }
 
-            let ProcRes{ stdout, .. } = proc_res;
+            let ProcRes { stdout, .. } = proc_res;
             srcs.push(stdout);
             round += 1;
         }
@@ -298,10 +321,13 @@ impl<'test> TestCx<'test> {
             Some(ref file) => {
                 let filepath = self.testpaths.file.parent().unwrap().join(file);
                 let mut s = String::new();
-                File::open(&filepath).unwrap().read_to_string(&mut s).unwrap();
+                File::open(&filepath)
+                    .unwrap()
+                    .read_to_string(&mut s)
+                    .unwrap();
                 s
             }
-            None => { srcs[srcs.len() - 2].clone() }
+            None => srcs[srcs.len() - 2].clone(),
         };
         let mut actual = srcs[srcs.len() - 1].clone();
 
@@ -315,7 +341,9 @@ impl<'test> TestCx<'test> {
         self.compare_source(&expected, &actual);
 
         // If we're only making sure that the output matches then just stop here
-        if self.props.pretty_compare_only { return; }
+        if self.props.pretty_compare_only {
+            return;
+        }
 
         // Finally, let's make sure it actually appears to remain valid code
         let proc_res = self.typecheck_source(actual);
@@ -323,7 +351,9 @@ impl<'test> TestCx<'test> {
             self.fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
         }
 
-        if !self.props.pretty_expanded { return }
+        if !self.props.pretty_expanded {
+            return;
+        }
 
         // additionally, run `--pretty expanded` and try to build it.
         let proc_res = self.print_source(srcs[round].clone(), "expanded");
@@ -331,12 +361,16 @@ impl<'test> TestCx<'test> {
             self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
         }
 
-        let ProcRes{ stdout: expanded_src, .. } = proc_res;
+        let ProcRes {
+            stdout: expanded_src,
+            ..
+        } = proc_res;
         let proc_res = self.typecheck_source(expanded_src);
         if !proc_res.status.success() {
             self.fatal_proc_rec(
                 "pretty-printed source (expanded) does not typecheck",
-                &proc_res);
+                &proc_res,
+            );
         }
     }
 
@@ -344,37 +378,42 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir_name();
 
         let mut rustc = Command::new(&self.config.rustc_path);
-        rustc.arg("-")
+        rustc
+            .arg("-")
             .arg("-Zunstable-options")
             .args(&["--unpretty", &pretty_type])
             .args(&["--target", &self.config.target])
-            .arg("-L").arg(&aux_dir)
+            .arg("-L")
+            .arg(&aux_dir)
             .args(self.split_maybe_args(&self.config.target_rustcflags))
             .args(&self.props.compile_flags)
             .envs(self.props.exec_env.clone());
 
-        self.compose_and_run(rustc,
-                             self.config.compile_lib_path.to_str().unwrap(),
-                             Some(aux_dir.to_str().unwrap()),
-                             Some(src))
+        self.compose_and_run(
+            rustc,
+            self.config.compile_lib_path.to_str().unwrap(),
+            Some(aux_dir.to_str().unwrap()),
+            Some(src),
+        )
     }
 
-    fn compare_source(&self,
-                      expected: &str,
-                      actual: &str) {
+    fn compare_source(&self, expected: &str, actual: &str) {
         if expected != actual {
             self.error("pretty-printed source does not match expected source");
-            println!("\n\
-expected:\n\
-------------------------------------------\n\
-{}\n\
-------------------------------------------\n\
-actual:\n\
-------------------------------------------\n\
-{}\n\
-------------------------------------------\n\
-\n",
-                     expected, actual);
+            println!(
+                "\n\
+                 expected:\n\
+                 ------------------------------------------\n\
+                 {}\n\
+                 ------------------------------------------\n\
+                 actual:\n\
+                 ------------------------------------------\n\
+                 {}\n\
+                 ------------------------------------------\n\
+                 \n",
+                expected,
+                actual
+            );
             panic!();
         }
     }
@@ -394,12 +433,16 @@ actual:\n\
 
         let aux_dir = self.aux_output_dir_name();
 
-        rustc.arg("-")
+        rustc
+            .arg("-")
             .arg("-Zno-trans")
-            .arg("--out-dir").arg(&out_dir)
+            .arg("--out-dir")
+            .arg(&out_dir)
             .arg(&format!("--target={}", target))
-            .arg("-L").arg(&self.config.build_base)
-            .arg("-L").arg(aux_dir);
+            .arg("-L")
+            .arg(&self.config.build_base)
+            .arg("-L")
+            .arg(aux_dir);
 
         if let Some(revision) = self.revision {
             rustc.args(&["--cfg", revision]);
@@ -417,7 +460,7 @@ actual:\n\
         let config = Config {
             target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
             host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            .. self.config.clone()
+            ..self.config.clone()
         };
 
         let test_cx = TestCx {
@@ -444,7 +487,7 @@ actual:\n\
         let DebuggerCommands {
             commands,
             check_lines,
-            breakpoint_lines
+            breakpoint_lines,
         } = self.parse_debugger_commands(prefixes);
         let mut cmds = commands.join("\n");
 
@@ -458,15 +501,12 @@ actual:\n\
 
         let debugger_run_result;
         match &*self.config.target {
-            "arm-linux-androideabi" |
-            "armv7-linux-androideabi" |
-            "aarch64-linux-android" => {
-
+            "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" => {
                 cmds = cmds.replace("run", "continue");
 
                 let tool_path = match self.config.android_cross_path.to_str() {
                     Some(x) => x.to_owned(),
-                    None => self.fatal("cannot find android cross path")
+                    None => self.fatal("cannot find android cross path"),
                 };
 
                 // write debugger script
@@ -475,15 +515,20 @@ actual:\n\
                 script_str.push_str(&format!("set sysroot {}\n", tool_path));
                 script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
                 script_str.push_str("target remote :5039\n");
-                script_str.push_str(&format!("set solib-search-path \
-                                              ./{}/stage2/lib/rustlib/{}/lib/\n",
-                                             self.config.host, self.config.target));
+                script_str.push_str(&format!(
+                    "set solib-search-path \
+                     ./{}/stage2/lib/rustlib/{}/lib/\n",
+                    self.config.host,
+                    self.config.target
+                ));
                 for line in &breakpoint_lines {
-                    script_str.push_str(&format!("break {:?}:{}\n",
-                                                 self.testpaths.file.file_name()
-                                                 .unwrap()
-                                                 .to_string_lossy(),
-                                                 *line)[..]);
+                    script_str.push_str(
+                        &format!(
+                            "break {:?}:{}\n",
+                            self.testpaths.file.file_name().unwrap().to_string_lossy(),
+                            *line
+                        )[..],
+                    );
                 }
                 script_str.push_str(&cmds);
                 script_str.push_str("\nquit\n");
@@ -505,14 +550,18 @@ actual:\n\
                     .status()
                     .expect(&format!("failed to exec `{:?}`", adb_path));
 
-                let adb_arg = format!("export LD_LIBRARY_PATH={}; \
-                                       gdbserver{} :5039 {}/{}",
-                                      self.config.adb_test_dir.clone(),
-                                      if self.config.target.contains("aarch64")
-                                      {"64"} else {""},
-                                      self.config.adb_test_dir.clone(),
-                                      exe_file.file_name().unwrap().to_str()
-                                      .unwrap());
+                let adb_arg = format!(
+                    "export LD_LIBRARY_PATH={}; \
+                     gdbserver{} :5039 {}/{}",
+                    self.config.adb_test_dir.clone(),
+                    if self.config.target.contains("aarch64") {
+                        "64"
+                    } else {
+                        ""
+                    },
+                    self.config.adb_test_dir.clone(),
+                    exe_file.file_name().unwrap().to_str().unwrap()
+                );
 
                 debug!("adb arg: {}", adb_arg);
                 let mut adb = Command::new(adb_path)
@@ -531,25 +580,26 @@ actual:\n\
                     line.truncate(0);
                     stdout.read_line(&mut line).unwrap();
                     if line.starts_with("Listening on port 5039") {
-                        break
+                        break;
                     }
                 }
                 drop(stdout);
 
                 let debugger_script = self.make_out_name("debugger.script");
                 // FIXME (#9639): This needs to handle non-utf8 paths
-                let debugger_opts =
-                    vec!["-quiet".to_owned(),
-                         "-batch".to_owned(),
-                         "-nx".to_owned(),
-                         format!("-command={}", debugger_script.to_str().unwrap())];
+                let debugger_opts = vec![
+                    "-quiet".to_owned(),
+                    "-batch".to_owned(),
+                    "-nx".to_owned(),
+                    format!("-command={}", debugger_script.to_str().unwrap()),
+                ];
 
                 let mut gdb_path = tool_path;
                 gdb_path.push_str("/bin/gdb");
                 let Output {
                     status,
                     stdout,
-                    stderr
+                    stderr,
                 } = Command::new(&gdb_path)
                     .args(&debugger_opts)
                     .output()
@@ -574,14 +624,15 @@ actual:\n\
             }
 
             _ => {
-                let rust_src_root = self.config.find_rust_src_root().expect(
-                    "Could not find Rust source root",
-                );
+                let rust_src_root = self.config
+                    .find_rust_src_root()
+                    .expect("Could not find Rust source root");
                 let rust_pp_module_rel_path = Path::new("./src/etc");
-                let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
-                                                           .to_str()
-                                                           .unwrap()
-                                                           .to_owned();
+                let rust_pp_module_abs_path = rust_src_root
+                    .join(rust_pp_module_rel_path)
+                    .to_str()
+                    .unwrap()
+                    .to_owned();
                 // write debugger script
                 let mut script_str = String::with_capacity(2048);
                 script_str.push_str(&format!("set charset {}\n", Self::charset()));
@@ -589,21 +640,25 @@ actual:\n\
 
                 match self.config.gdb_version {
                     Some(version) => {
-                        println!("NOTE: compiletest thinks it is using GDB version {}",
-                                 version);
+                        println!(
+                            "NOTE: compiletest thinks it is using GDB version {}",
+                            version
+                        );
 
                         if version > extract_gdb_version("7.4").unwrap() {
                             // Add the directory containing the pretty printers to
                             // GDB's script auto loading safe path
-                            script_str.push_str(
-                                &format!("add-auto-load-safe-path {}\n",
-                                         rust_pp_module_abs_path.replace(r"\", r"\\"))
-                            );
+                            script_str.push_str(&format!(
+                                "add-auto-load-safe-path {}\n",
+                                rust_pp_module_abs_path.replace(r"\", r"\\")
+                            ));
                         }
                     }
                     _ => {
-                        println!("NOTE: compiletest does not know which version of \
-                                  GDB it is using");
+                        println!(
+                            "NOTE: compiletest does not know which version of \
+                             GDB it is using"
+                        );
                     }
                 }
 
@@ -612,13 +667,13 @@ actual:\n\
                 script_str.push_str("set print pretty off\n");
 
                 // Add the pretty printer directory to GDB's source-file search path
-                script_str.push_str(&format!("directory {}\n",
-                                             rust_pp_module_abs_path));
+                script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path));
 
                 // Load the target executable
-                script_str.push_str(&format!("file {}\n",
-                                             exe_file.to_str().unwrap()
-                                             .replace(r"\", r"\\")));
+                script_str.push_str(&format!(
+                    "file {}\n",
+                    exe_file.to_str().unwrap().replace(r"\", r"\\")
+                ));
 
                 // Force GDB to print values in the Rust format.
                 if self.config.gdb_native_rust {
@@ -627,10 +682,11 @@ actual:\n\
 
                 // Add line breakpoints
                 for line in &breakpoint_lines {
-                    script_str.push_str(&format!("break '{}':{}\n",
-                                                 self.testpaths.file.file_name().unwrap()
-                                                 .to_string_lossy(),
-                                                 *line));
+                    script_str.push_str(&format!(
+                        "break '{}':{}\n",
+                        self.testpaths.file.file_name().unwrap().to_string_lossy(),
+                        *line
+                    ));
                 }
 
                 script_str.push_str(&cmds);
@@ -642,21 +698,23 @@ actual:\n\
                 let debugger_script = self.make_out_name("debugger.script");
 
                 // FIXME (#9639): This needs to handle non-utf8 paths
-                let debugger_opts =
-                    vec!["-quiet".to_owned(),
-                         "-batch".to_owned(),
-                         "-nx".to_owned(),
-                         format!("-command={}", debugger_script.to_str().unwrap())];
+                let debugger_opts = vec![
+                    "-quiet".to_owned(),
+                    "-batch".to_owned(),
+                    "-nx".to_owned(),
+                    format!("-command={}", debugger_script.to_str().unwrap()),
+                ];
 
                 let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
                 gdb.args(&debugger_opts)
                     .env("PYTHONPATH", rust_pp_module_abs_path);
 
-                debugger_run_result =
-                    self.compose_and_run(gdb,
-                                         self.config.run_lib_path.to_str().unwrap(),
-                                         None,
-                                         None);
+                debugger_run_result = self.compose_and_run(
+                    gdb,
+                    self.config.run_lib_path.to_str().unwrap(),
+                    None,
+                    None,
+                );
             }
         }
 
@@ -677,7 +735,7 @@ actual:\n\
         let config = Config {
             target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
             host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            .. self.config.clone()
+            ..self.config.clone()
         };
 
 
@@ -700,12 +758,16 @@ actual:\n\
 
         match self.config.lldb_version {
             Some(ref version) => {
-                println!("NOTE: compiletest thinks it is using LLDB version {}",
-                         version);
+                println!(
+                    "NOTE: compiletest thinks it is using LLDB version {}",
+                    version
+                );
             }
             _ => {
-                println!("NOTE: compiletest does not know which version of \
-                          LLDB it is using");
+                println!(
+                    "NOTE: compiletest does not know which version of \
+                     LLDB it is using"
+                );
             }
         }
 
@@ -725,17 +787,18 @@ actual:\n\
         script_str.push_str("version\n");
 
         // Switch LLDB into "Rust mode"
-        let rust_src_root = self.config.find_rust_src_root().expect(
-            "Could not find Rust source root",
-        );
+        let rust_src_root = self.config
+            .find_rust_src_root()
+            .expect("Could not find Rust source root");
         let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py");
-        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
-                                                   .to_str()
-                                                   .unwrap()
-                                                   .to_owned();
-
-        script_str.push_str(&format!("command script import {}\n",
-                                     &rust_pp_module_abs_path[..])[..]);
+        let rust_pp_module_abs_path = rust_src_root
+            .join(rust_pp_module_rel_path)
+            .to_str()
+            .unwrap()
+            .to_owned();
+
+        script_str
+            .push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[..]);
         script_str.push_str("type summary add --no-value ");
         script_str.push_str("--python-function lldb_rust_formatters.print_val ");
         script_str.push_str("-x \".*\" --category Rust\n");
@@ -744,9 +807,11 @@ actual:\n\
         // Set breakpoints on every line that contains the string "#break"
         let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
         for line in &breakpoint_lines {
-            script_str.push_str(&format!("breakpoint set --file '{}' --line {}\n",
-                                         source_file_name,
-                                         line));
+            script_str.push_str(&format!(
+                "breakpoint set --file '{}' --line {}\n",
+                source_file_name,
+                line
+            ));
         }
 
         // Append the other commands
@@ -764,9 +829,7 @@ actual:\n\
         let debugger_script = self.make_out_name("debugger.script");
 
         // Let LLDB execute the script via lldb_batchmode.py
-        let debugger_run_result = self.run_lldb(&exe_file,
-                                                &debugger_script,
-                                                &rust_src_root);
+        let debugger_run_result = self.run_lldb(&exe_file, &debugger_script, &rust_src_root);
 
         if !debugger_run_result.status.success() {
             self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
@@ -775,32 +838,39 @@ actual:\n\
         self.check_debugger_output(&debugger_run_result, &check_lines);
     }
 
-    fn run_lldb(&self,
-                test_executable: &Path,
-                debugger_script: &Path,
-                rust_src_root: &Path)
-                -> ProcRes {
+    fn run_lldb(
+        &self,
+        test_executable: &Path,
+        debugger_script: &Path,
+        rust_src_root: &Path,
+    ) -> ProcRes {
         // Prepare the lldb_batchmode which executes the debugger script
         let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
-        self.cmd2procres(Command::new(&self.config.lldb_python)
-                         .arg(&lldb_script_path)
-                         .arg(test_executable)
-                         .arg(debugger_script)
-                         .env("PYTHONPATH",
-                              self.config.lldb_python_dir.as_ref().unwrap()))
+        self.cmd2procres(
+            Command::new(&self.config.lldb_python)
+                .arg(&lldb_script_path)
+                .arg(test_executable)
+                .arg(debugger_script)
+                .env("PYTHONPATH", self.config.lldb_python_dir.as_ref().unwrap()),
+        )
     }
 
     fn cmd2procres(&self, cmd: &mut Command) -> ProcRes {
         let (status, out, err) = match cmd.output() {
-            Ok(Output { status, stdout, stderr }) => {
-                (status,
-                 String::from_utf8(stdout).unwrap(),
-                 String::from_utf8(stderr).unwrap())
-            },
-            Err(e) => {
-                self.fatal(&format!("Failed to setup Python process for \
-                                      LLDB script: {}", e))
-            }
+            Ok(Output {
+                status,
+                stdout,
+                stderr,
+            }) => (
+                status,
+                String::from_utf8(stdout).unwrap(),
+                String::from_utf8(stderr).unwrap(),
+            ),
+            Err(e) => self.fatal(&format!(
+                "Failed to setup Python process for \
+                 LLDB script: {}",
+                e
+            )),
         };
 
         self.dump_output(&out, &err);
@@ -808,15 +878,17 @@ actual:\n\
             status,
             stdout: out,
             stderr: err,
-            cmdline: format!("{:?}", cmd)
+            cmdline: format!("{:?}", cmd),
         }
     }
 
     fn parse_debugger_commands(&self, debugger_prefixes: &[&str]) -> DebuggerCommands {
-        let directives = debugger_prefixes.iter().map(|prefix| (
-            format!("{}-command", prefix),
-            format!("{}-check", prefix),
-        )).collect::<Vec<_>>();
+        let directives = debugger_prefixes
+            .iter()
+            .map(|prefix| {
+                (format!("{}-command", prefix), format!("{}-check", prefix))
+            })
+            .collect::<Vec<_>>();
 
         let mut breakpoint_lines = vec![];
         let mut commands = vec![];
@@ -831,22 +903,16 @@ actual:\n\
                     }
 
                     for &(ref command_directive, ref check_directive) in &directives {
-                        self.config.parse_name_value_directive(
-                            &line,
-                            command_directive).map(|cmd| {
-                                commands.push(cmd)
-                            });
-
-                        self.config.parse_name_value_directive(
-                            &line,
-                            check_directive).map(|cmd| {
-                                check_lines.push(cmd)
-                            });
+                        self.config
+                            .parse_name_value_directive(&line, command_directive)
+                            .map(|cmd| commands.push(cmd));
+
+                        self.config
+                            .parse_name_value_directive(&line, check_directive)
+                            .map(|cmd| check_lines.push(cmd));
                     }
                 }
-                Err(e) => {
-                    self.fatal(&format!("Error while parsing debugger commands: {}", e))
-                }
+                Err(e) => self.fatal(&format!("Error while parsing debugger commands: {}", e)),
             }
             counter += 1;
         }
@@ -864,15 +930,11 @@ actual:\n\
         }
 
         // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
-        let options_to_remove = [
-            "-O".to_owned(),
-            "-g".to_owned(),
-            "--debuginfo".to_owned()
-        ];
-        let new_options =
-            self.split_maybe_args(options).into_iter()
-                                          .filter(|x| !options_to_remove.contains(x))
-                                          .collect::<Vec<String>>();
+        let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
+        let new_options = self.split_maybe_args(options)
+            .into_iter()
+            .filter(|x| !options_to_remove.contains(x))
+            .collect::<Vec<String>>();
 
         Some(new_options.join(" "))
     }
@@ -891,9 +953,13 @@ actual:\n\
             }
         }
         if check_line_index != num_check_lines && num_check_lines > 0 {
-            self.fatal_proc_rec(&format!("line not found in debugger output: {}",
-                                         check_lines[check_line_index]),
-                                debugger_run_result);
+            self.fatal_proc_rec(
+                &format!(
+                    "line not found in debugger output: {}",
+                    check_lines[check_line_index]
+                ),
+                debugger_run_result,
+            );
         }
 
         fn check_single_line(line: &str, check_line: &str) -> bool {
@@ -904,17 +970,18 @@ actual:\n\
             let can_start_anywhere = check_line.starts_with("[...]");
             let can_end_anywhere = check_line.ends_with("[...]");
 
-            let check_fragments: Vec<&str> = check_line.split("[...]")
-                                                       .filter(|frag| !frag.is_empty())
-                                                       .collect();
+            let check_fragments: Vec<&str> = check_line
+                .split("[...]")
+                .filter(|frag| !frag.is_empty())
+                .collect();
             if check_fragments.is_empty() {
                 return true;
             }
 
             let (mut rest, first_fragment) = if can_start_anywhere {
                 match line.find(check_fragments[0]) {
-                    Some(pos) => (&line[pos + check_fragments[0].len() ..], 1),
-                    None => return false
+                    Some(pos) => (&line[pos + check_fragments[0].len()..], 1),
+                    None => return false,
                 }
             } else {
                 (line, 0)
@@ -923,9 +990,9 @@ actual:\n\
             for current_fragment in &check_fragments[first_fragment..] {
                 match rest.find(current_fragment) {
                     Some(pos) => {
-                        rest = &rest[pos + current_fragment.len() .. ];
+                        rest = &rest[pos + current_fragment.len()..];
                     }
-                    None => return false
+                    None => return false,
                 }
             }
 
@@ -937,15 +1004,15 @@ actual:\n\
         }
     }
 
-    fn check_error_patterns(&self,
-                            output_to_check: &str,
-                            proc_res: &ProcRes) {
+    fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
         if self.props.error_patterns.is_empty() {
             if self.props.must_compile_successfully {
-                return
+                return;
             } else {
-                self.fatal(&format!("no error pattern specified in {:?}",
-                                    self.testpaths.file.display()));
+                self.fatal(&format!(
+                    "no error pattern specified in {:?}",
+                    self.testpaths.file.display()
+                ));
             }
         }
         let mut next_err_idx = 0;
@@ -963,13 +1030,16 @@ actual:\n\
                 next_err_pat = self.props.error_patterns[next_err_idx].trim();
             }
         }
-        if done { return; }
+        if done {
+            return;
+        }
 
         let missing_patterns = &self.props.error_patterns[next_err_idx..];
         if missing_patterns.len() == 1 {
             self.fatal_proc_rec(
                 &format!("error pattern '{}' not found!", missing_patterns[0]),
-                proc_res);
+                proc_res,
+            );
         } else {
             for pattern in missing_patterns {
                 self.error(&format!("error pattern '{}' not found!", *pattern));
@@ -986,9 +1056,7 @@ actual:\n\
         }
     }
 
-    fn check_forbid_output(&self,
-                           output_to_check: &str,
-                           proc_res: &ProcRes) {
+    fn check_forbid_output(&self, output_to_check: &str, proc_res: &ProcRes) {
         for pat in &self.props.forbid_output {
             if output_to_check.contains(pat) {
                 self.fatal_proc_rec("forbidden pattern found in compiler output", proc_res);
@@ -996,41 +1064,42 @@ actual:\n\
         }
     }
 
-    fn check_expected_errors(&self,
-                             expected_errors: Vec<errors::Error>,
-                             proc_res: &ProcRes) {
-        if proc_res.status.success() &&
-            expected_errors.iter().any(|x| x.kind == Some(ErrorKind::Error)) {
+    fn check_expected_errors(&self, expected_errors: Vec<errors::Error>, proc_res: &ProcRes) {
+        if proc_res.status.success()
+            && expected_errors
+                .iter()
+                .any(|x| x.kind == Some(ErrorKind::Error))
+        {
             self.fatal_proc_rec("process did not return an error status", proc_res);
         }
 
-        let file_name =
-            format!("{}", self.testpaths.file.display())
-            .replace(r"\", "/"); // on windows, translate all '\' path separators to '/'
+        // on windows, translate all '\' path separators to '/'
+        let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/");
 
         // If the testcase being checked contains at least one expected "help"
         // message, then we'll ensure that all "help" messages are expected.
         // Otherwise, all "help" messages reported by the compiler will be ignored.
         // This logic also applies to "note" messages.
-        let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help));
-        let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
+        let expect_help = expected_errors
+            .iter()
+            .any(|ee| ee.kind == Some(ErrorKind::Help));
+        let expect_note = expected_errors
+            .iter()
+            .any(|ee| ee.kind == Some(ErrorKind::Note));
 
         // Parse the JSON output from the compiler and extract out the messages.
         let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res);
         let mut unexpected = Vec::new();
         let mut found = vec![false; expected_errors.len()];
         for actual_error in &actual_errors {
-            let opt_index =
-                expected_errors
-                .iter()
-                .enumerate()
-                .position(|(index, expected_error)| {
-                    !found[index] &&
-                        actual_error.line_num == expected_error.line_num &&
-                        (expected_error.kind.is_none() ||
-                         actual_error.kind == expected_error.kind) &&
-                        actual_error.msg.contains(&expected_error.msg)
-                });
+            let opt_index = expected_errors.iter().enumerate().position(
+                |(index, expected_error)| {
+                    !found[index] && actual_error.line_num == expected_error.line_num
+                        && (expected_error.kind.is_none()
+                            || actual_error.kind == expected_error.kind)
+                        && actual_error.msg.contains(&expected_error.msg)
+                },
+            );
 
             match opt_index {
                 Some(index) => {
@@ -1041,14 +1110,16 @@ actual:\n\
 
                 None => {
                     if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
-                        self.error(
-                            &format!("{}:{}: unexpected {}: '{}'",
-                                     file_name,
-                                     actual_error.line_num,
-                                     actual_error.kind.as_ref()
-                                     .map_or(String::from("message"),
-                                             |k| k.to_string()),
-                                     actual_error.msg));
+                        self.error(&format!(
+                            "{}:{}: unexpected {}: '{}'",
+                            file_name,
+                            actual_error.line_num,
+                            actual_error
+                                .kind
+                                .as_ref()
+                                .map_or(String::from("message"), |k| k.to_string()),
+                            actual_error.msg
+                        ));
                         unexpected.push(actual_error);
                     }
                 }
@@ -1059,24 +1130,27 @@ actual:\n\
         // anything not yet found is a problem
         for (index, expected_error) in expected_errors.iter().enumerate() {
             if !found[index] {
-                self.error(
-                    &format!("{}:{}: expected {} not found: {}",
-                             file_name,
-                             expected_error.line_num,
-                             expected_error.kind.as_ref()
-                             .map_or("message".into(),
-                                     |k| k.to_string()),
-                             expected_error.msg));
+                self.error(&format!(
+                    "{}:{}: expected {} not found: {}",
+                    file_name,
+                    expected_error.line_num,
+                    expected_error
+                        .kind
+                        .as_ref()
+                        .map_or("message".into(), |k| k.to_string()),
+                    expected_error.msg
+                ));
                 not_found.push(expected_error);
             }
         }
 
         if !unexpected.is_empty() || !not_found.is_empty() {
-            self.error(
-                &format!("{} unexpected errors found, {} expected errors not found",
-                         unexpected.len(), not_found.len()));
-            println!("status: {}\ncommand: {}",
-                   proc_res.status, proc_res.cmdline);
+            self.error(&format!(
+                "{} unexpected errors found, {} expected errors not found",
+                unexpected.len(),
+                not_found.len()
+            ));
+            println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline);
             if !unexpected.is_empty() {
                 println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
             }
@@ -1091,24 +1165,25 @@ actual:\n\
     /// which did not match any of the expected error. We always require
     /// errors/warnings to be explicitly listed, but only require
     /// helps/notes if there are explicit helps/notes given.
-    fn is_unexpected_compiler_message(&self,
-                                      actual_error: &Error,
-                                      expect_help: bool,
-                                      expect_note: bool)
-                                      -> bool {
+    fn is_unexpected_compiler_message(
+        &self,
+        actual_error: &Error,
+        expect_help: bool,
+        expect_note: bool,
+    ) -> bool {
         match actual_error.kind {
             Some(ErrorKind::Help) => expect_help,
             Some(ErrorKind::Note) => expect_note,
-            Some(ErrorKind::Error) |
-            Some(ErrorKind::Warning) => true,
-            Some(ErrorKind::Suggestion) |
-            None => false
+            Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
+            Some(ErrorKind::Suggestion) | None => false,
         }
     }
 
     fn compile_test(&self) -> ProcRes {
         let mut rustc = self.make_compile_args(
-            &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name()));
+            &self.testpaths.file,
+            TargetLocation::ThisFile(self.make_exe_name()),
+        );
 
         rustc.arg("-L").arg(&self.aux_output_dir_name());
 
@@ -1131,14 +1206,14 @@ actual:\n\
         if self.props.build_aux_docs {
             for rel_ab in &self.props.aux_builds {
                 let aux_testpaths = self.compute_aux_test_paths(rel_ab);
-                let aux_props = self.props.from_aux_file(&aux_testpaths.file,
-                                                         self.revision,
-                                                         self.config);
+                let aux_props =
+                    self.props
+                        .from_aux_file(&aux_testpaths.file, self.revision, self.config);
                 let aux_cx = TestCx {
                     config: self.config,
                     props: &aux_props,
                     testpaths: &aux_testpaths,
-                    revision: self.revision
+                    revision: self.revision,
                 };
                 let auxres = aux_cx.document(out_dir);
                 if !auxres.status.success() {
@@ -1149,15 +1224,25 @@ actual:\n\
 
         let aux_dir = self.aux_output_dir_name();
 
-        let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed");
+        let rustdoc_path = self.config
+            .rustdoc_path
+            .as_ref()
+            .expect("--rustdoc-path passed");
         let mut rustdoc = Command::new(rustdoc_path);
 
-        rustdoc.arg("-L").arg(aux_dir)
-            .arg("-o").arg(out_dir)
+        rustdoc
+            .arg("-L")
+            .arg(aux_dir)
+            .arg("-o")
+            .arg(out_dir)
             .arg(&self.testpaths.file)
             .args(&self.props.compile_flags);
         if let Some(ref linker) = self.config.linker {
-            rustdoc.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
+            rustdoc
+                .arg("--linker")
+                .arg(linker)
+                .arg("-Z")
+                .arg("unstable-options");
         }
 
         self.compose_and_run_compiler(rustdoc, None)
@@ -1187,34 +1272,39 @@ actual:\n\
                     for entry in entries {
                         let entry = entry.unwrap();
                         if !entry.path().is_file() {
-                            continue
+                            continue;
                         }
                         prog.push_str(":");
                         prog.push_str(entry.path().to_str().unwrap());
                     }
                 }
-                let mut test_client = Command::new(
-                    self.config.remote_test_client.as_ref().unwrap());
+                let mut test_client =
+                    Command::new(self.config.remote_test_client.as_ref().unwrap());
                 test_client
                     .args(&["run", &prog])
                     .args(args)
                     .envs(env.clone());
-                self.compose_and_run(test_client,
-                                     self.config.run_lib_path.to_str().unwrap(),
-                                     Some(aux_dir.to_str().unwrap()),
-                                     None)
+                self.compose_and_run(
+                    test_client,
+                    self.config.run_lib_path.to_str().unwrap(),
+                    Some(aux_dir.to_str().unwrap()),
+                    None,
+                )
             }
             _ => {
                 let aux_dir = self.aux_output_dir_name();
                 let ProcArgs { prog, args } = self.make_run_args();
                 let mut program = Command::new(&prog);
-                program.args(args)
+                program
+                    .args(args)
                     .current_dir(&self.output_base_name().parent().unwrap())
                     .envs(env.clone());
-                self.compose_and_run(program,
-                                     self.config.run_lib_path.to_str().unwrap(),
-                                     Some(aux_dir.to_str().unwrap()),
-                                     None)
+                self.compose_and_run(
+                    program,
+                    self.config.run_lib_path.to_str().unwrap(),
+                    Some(aux_dir.to_str().unwrap()),
+                    None,
+                )
             }
         }
     }
@@ -1222,24 +1312,29 @@ actual:\n\
     /// For each `aux-build: foo/bar` annotation, we check to find the
     /// file in a `aux` directory relative to the test itself.
     fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths {
-        let test_ab = self.testpaths.file
-                                    .parent()
-                                    .expect("test file path has no parent")
-                                    .join("auxiliary")
-                                    .join(rel_ab);
+        let test_ab = self.testpaths
+            .file
+            .parent()
+            .expect("test file path has no parent")
+            .join("auxiliary")
+            .join(rel_ab);
         if !test_ab.exists() {
-            self.fatal(&format!("aux-build `{}` source not found", test_ab.display()))
+            self.fatal(&format!(
+                "aux-build `{}` source not found",
+                test_ab.display()
+            ))
         }
 
         TestPaths {
             file: test_ab,
             base: self.testpaths.base.clone(),
-            relative_dir: self.testpaths.relative_dir
-                                        .join("auxiliary")
-                                        .join(rel_ab)
-                                        .parent()
-                                        .expect("aux-build path has no parent")
-                                        .to_path_buf()
+            relative_dir: self.testpaths
+                .relative_dir
+                .join("auxiliary")
+                .join(rel_ab)
+                .parent()
+                .expect("aux-build path has no parent")
+                .to_path_buf(),
         }
     }
 
@@ -1252,9 +1347,9 @@ actual:\n\
 
         for rel_ab in &self.props.aux_builds {
             let aux_testpaths = self.compute_aux_test_paths(rel_ab);
-            let aux_props = self.props.from_aux_file(&aux_testpaths.file,
-                                                     self.revision,
-                                                     self.config);
+            let aux_props =
+                self.props
+                    .from_aux_file(&aux_testpaths.file, self.revision, self.config);
             let aux_output = {
                 let f = self.make_lib_name(&self.testpaths.file);
                 let parent = f.parent().unwrap();
@@ -1264,15 +1359,16 @@ actual:\n\
                 config: self.config,
                 props: &aux_props,
                 testpaths: &aux_testpaths,
-                revision: self.revision
+                revision: self.revision,
             };
             let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
 
             let crate_type = if aux_props.no_prefer_dynamic {
                 None
-            } else if (self.config.target.contains("musl") && !aux_props.force_host) ||
-                      self.config.target.contains("wasm32") ||
-                      self.config.target.contains("emscripten") {
+            } else if (self.config.target.contains("musl") && !aux_props.force_host)
+                || self.config.target.contains("wasm32")
+                || self.config.target.contains("emscripten")
+            {
                 // We primarily compile all auxiliary libraries as dynamic libraries
                 // to avoid code size bloat and large binaries as much as possible
                 // for the test suite (otherwise including libstd statically in all
@@ -1293,32 +1389,40 @@ actual:\n\
 
             aux_rustc.arg("-L").arg(&aux_dir);
 
-            let auxres = aux_cx.compose_and_run(aux_rustc,
-                                                aux_cx.config.compile_lib_path.to_str().unwrap(),
-                                                Some(aux_dir.to_str().unwrap()),
-                                                None);
+            let auxres = aux_cx.compose_and_run(
+                aux_rustc,
+                aux_cx.config.compile_lib_path.to_str().unwrap(),
+                Some(aux_dir.to_str().unwrap()),
+                None,
+            );
             if !auxres.status.success() {
                 self.fatal_proc_rec(
-                    &format!("auxiliary build of {:?} failed to compile: ",
-                             aux_testpaths.file.display()),
-                    &auxres);
+                    &format!(
+                        "auxiliary build of {:?} failed to compile: ",
+                        aux_testpaths.file.display()
+                    ),
+                    &auxres,
+                );
             }
         }
 
         rustc.envs(self.props.rustc_env.clone());
-        self.compose_and_run(rustc,
-                             self.config.compile_lib_path.to_str().unwrap(),
-                             Some(aux_dir.to_str().unwrap()),
-                             input)
-    }
-
-    fn compose_and_run(&self,
-                       mut command: Command,
-                       lib_path: &str,
-                       aux_path: Option<&str>,
-                       input: Option<String>) -> ProcRes {
-        let cmdline =
-        {
+        self.compose_and_run(
+            rustc,
+            self.config.compile_lib_path.to_str().unwrap(),
+            Some(aux_dir.to_str().unwrap()),
+            input,
+        )
+    }
+
+    fn compose_and_run(
+        &self,
+        mut command: Command,
+        lib_path: &str,
+        aux_path: Option<&str>,
+        input: Option<String>,
+    ) -> ProcRes {
+        let cmdline = {
             let cmdline = self.make_cmdline(&command, lib_path);
             logv(self.config, format!("executing {}", cmdline));
             cmdline
@@ -1342,13 +1446,23 @@ actual:\n\
         let newpath = env::join_paths(&path).unwrap();
         command.env(dylib_env_var(), newpath);
 
-        let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command));
+        let mut child = command
+            .spawn()
+            .expect(&format!("failed to exec `{:?}`", &command));
         if let Some(input) = input {
-            child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
+            child
+                .stdin
+                .as_mut()
+                .unwrap()
+                .write_all(input.as_bytes())
+                .unwrap();
         }
 
-        let Output { status, stdout, stderr } = read2_abbreviated(child)
-            .expect("failed to read output");
+        let Output {
+            status,
+            stdout,
+            stderr,
+        } = read2_abbreviated(child).expect("failed to read output");
 
         let result = ProcRes {
             status,
@@ -1364,11 +1478,11 @@ actual:\n\
 
     fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
         let mut rustc = Command::new(&self.config.rustc_path);
-        rustc.arg(input_file)
-            .arg("-L").arg(&self.config.build_base);
+        rustc.arg(input_file).arg("-L").arg(&self.config.build_base);
 
         // Optionally prevent default --target if specified in test compile-flags.
-        let custom_target = self.props.compile_flags
+        let custom_target = self.props
+            .compile_flags
             .iter()
             .any(|x| x.starts_with("--target"));
 
@@ -1387,15 +1501,16 @@ actual:\n\
         }
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
-            rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
+            rustc.args(&[
+                "-Z",
+                &format!("incremental={}", incremental_dir.display()),
+            ]);
             rustc.args(&["-Z", "incremental-verify-ich"]);
             rustc.args(&["-Z", "incremental-queries"]);
         }
 
         match self.config.mode {
-            CompileFail |
-            ParseFail |
-            Incremental => {
+            CompileFail | ParseFail | Incremental => {
                 // If we are extracting and matching errors in the new
                 // fashion, then you want JSON mode. Old-skool error
                 // patterns still match the raw compiler output.
@@ -1403,16 +1518,19 @@ actual:\n\
                     rustc.args(&["--error-format", "json"]);
                 }
             }
-            Ui => {
-                if !self.props.compile_flags.iter().any(|s| s.starts_with("--error-format")) {
-                    rustc.args(&["--error-format", "json"]);
-                }
-            }
+            Ui => if !self.props
+                .compile_flags
+                .iter()
+                .any(|s| s.starts_with("--error-format"))
+            {
+                rustc.args(&["--error-format", "json"]);
+            },
             MirOpt => {
                 rustc.args(&[
                     "-Zdump-mir=all",
                     "-Zmir-opt-level=3",
-                    "-Zdump-mir-exclude-pass-number"]);
+                    "-Zdump-mir-exclude-pass-number",
+                ]);
 
                 let mir_dump_dir = self.get_mir_dump_dir();
                 let _ = fs::remove_dir_all(&mir_dump_dir);
@@ -1532,26 +1650,21 @@ actual:\n\
         args.extend(self.split_maybe_args(&self.props.run_flags));
 
         let prog = args.remove(0);
-         ProcArgs {
-            prog,
-            args,
-        }
+        ProcArgs { prog, args }
     }
 
     fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> {
         match *argstr {
-            Some(ref s) => {
-                s
-                    .split(' ')
-                    .filter_map(|s| {
-                        if s.chars().all(|c| c.is_whitespace()) {
-                            None
-                        } else {
-                            Some(s.to_owned())
-                        }
-                    }).collect()
-            }
-            None => Vec::new()
+            Some(ref s) => s.split(' ')
+                .filter_map(|s| {
+                    if s.chars().all(|c| c.is_whitespace()) {
+                        None
+                    } else {
+                        Some(s.to_owned())
+                    }
+                })
+                .collect(),
+            None => Vec::new(),
         }
     }
 
@@ -1565,7 +1678,11 @@ actual:\n\
             // Build the LD_LIBRARY_PATH variable as it would be seen on the command line
             // for diagnostic purposes
             fn lib_path_cmd_prefix(path: &str) -> String {
-                format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
+                format!(
+                    "{}=\"{}\"",
+                    util::lib_path_env_var(),
+                    util::make_new_path(path)
+                )
             }
 
             format!("{} {:?}", lib_path_cmd_prefix(libpath), command)
@@ -1584,11 +1701,12 @@ actual:\n\
         self.maybe_dump_to_stdout(out, err);
     }
 
-    fn dump_output_file(&self,
-                        out: &str,
-                        extension: &str) {
+    fn dump_output_file(&self, out: &str, extension: &str) {
         let outfile = self.make_out_name(extension);
-        File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap();
+        File::create(&outfile)
+            .unwrap()
+            .write_all(out.as_bytes())
+            .unwrap();
     }
 
     fn make_out_name(&self, extension: &str) -> PathBuf {
@@ -1613,8 +1731,7 @@ actual:\n\
         let dir = self.config.build_base.join(&self.testpaths.relative_dir);
 
         // Note: The directory `dir` is created during `collect_tests_from_dir`
-        dir
-            .join(&self.output_testname(&self.testpaths.file))
+        dir.join(&self.output_testname(&self.testpaths.file))
             .with_extension(&self.config.stage_id)
     }
 
@@ -1631,12 +1748,13 @@ actual:\n\
     fn error(&self, err: &str) {
         match self.revision {
             Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),
-            None => println!("\nerror: {}", err)
+            None => println!("\nerror: {}", err),
         }
     }
 
     fn fatal(&self, err: &str) -> ! {
-        self.error(err); panic!();
+        self.error(err);
+        panic!();
     }
 
     fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! {
@@ -1652,10 +1770,10 @@ actual:\n\
     // errors here.
     fn try_print_open_handles(&self) {
         if !cfg!(windows) {
-            return
+            return;
         }
         if self.config.mode != Incremental {
-            return
+            return;
         }
 
         let filename = match self.testpaths.file.file_stem() {
@@ -1689,11 +1807,10 @@ actual:\n\
     fn compile_test_and_save_ir(&self) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
 
-        let output_file = TargetLocation::ThisDirectory(
-            self.output_base_name().parent().unwrap().to_path_buf());
+        let output_file =
+            TargetLocation::ThisDirectory(self.output_base_name().parent().unwrap().to_path_buf());
         let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
-        rustc.arg("-L").arg(aux_dir)
-            .arg("--emit=llvm-ir");
+        rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir");
 
         self.compose_and_run_compiler(rustc, None)
     }
@@ -1701,7 +1818,9 @@ actual:\n\
     fn check_ir_with_filecheck(&self) -> ProcRes {
         let irfile = self.output_base_name().with_extension("ll");
         let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
-        filecheck.arg("--input-file").arg(irfile)
+        filecheck
+            .arg("--input-file")
+            .arg(irfile)
             .arg(&self.testpaths.file);
         self.compose_and_run(filecheck, "", None, None)
     }
@@ -1763,105 +1882,119 @@ actual:\n\
         }
     }
 
-    fn get_lines<P: AsRef<Path>>(&self, path: &P,
-                                 mut other_files: Option<&mut Vec<String>>) -> Vec<usize> {
-        let mut file = fs::File::open(path)
-                                .expect("markdown_test_output_check_entry File::open failed");
+    fn get_lines<P: AsRef<Path>>(
+        &self,
+        path: &P,
+        mut other_files: Option<&mut Vec<String>>,
+    ) -> Vec<usize> {
+        let mut file =
+            fs::File::open(path).expect("markdown_test_output_check_entry File::open failed");
         let mut content = String::new();
         file.read_to_string(&mut content)
             .expect("markdown_test_output_check_entry read_to_string failed");
         let mut ignore = false;
-        content.lines()
-               .enumerate()
-               .filter_map(|(line_nb, line)| {
-                   if (line.trim_left().starts_with("pub mod ") ||
-                       line.trim_left().starts_with("mod ")) &&
-                      line.ends_with(';') {
-                       if let Some(ref mut other_files) = other_files {
-                           other_files.push(line.rsplit("mod ")
-                                      .next()
-                                      .unwrap()
-                                      .replace(";", ""));
-                       }
-                       None
-                   } else {
-                       let sline = line.split("///").last().unwrap_or("");
-                       let line = sline.trim_left();
-                       if line.starts_with("```") {
-                           if ignore {
-                               ignore = false;
-                               None
-                           } else {
-                               ignore = true;
-                               Some(line_nb + 1)
-                           }
-                       } else {
-                           None
-                       }
-                   }
-               })
-               .collect()
+        content
+            .lines()
+            .enumerate()
+            .filter_map(|(line_nb, line)| {
+                if (line.trim_left().starts_with("pub mod ")
+                    || line.trim_left().starts_with("mod "))
+                    && line.ends_with(';')
+                {
+                    if let Some(ref mut other_files) = other_files {
+                        other_files.push(line.rsplit("mod ").next().unwrap().replace(";", ""));
+                    }
+                    None
+                } else {
+                    let sline = line.split("///").last().unwrap_or("");
+                    let line = sline.trim_left();
+                    if line.starts_with("```") {
+                        if ignore {
+                            ignore = false;
+                            None
+                        } else {
+                            ignore = true;
+                            Some(line_nb + 1)
+                        }
+                    } else {
+                        None
+                    }
+                }
+            })
+            .collect()
     }
 
     fn check_rustdoc_test_option(&self, res: ProcRes) {
         let mut other_files = Vec::new();
         let mut files: HashMap<String, Vec<usize>> = HashMap::new();
         let cwd = env::current_dir().unwrap();
-        files.insert(self.testpaths.file.strip_prefix(&cwd)
-                                        .unwrap_or(&self.testpaths.file)
-                                        .to_str()
-                                        .unwrap()
-                                        .replace('\\', "/"),
-                     self.get_lines(&self.testpaths.file, Some(&mut other_files)));
+        files.insert(
+            self.testpaths
+                .file
+                .strip_prefix(&cwd)
+                .unwrap_or(&self.testpaths.file)
+                .to_str()
+                .unwrap()
+                .replace('\\', "/"),
+            self.get_lines(&self.testpaths.file, Some(&mut other_files)),
+        );
         for other_file in other_files {
             let mut path = self.testpaths.file.clone();
             path.set_file_name(&format!("{}.rs", other_file));
-            files.insert(path.strip_prefix(&cwd)
-                             .unwrap_or(&path)
-                             .to_str()
-                             .unwrap()
-                             .replace('\\', "/"),
-                         self.get_lines(&path, None));
+            files.insert(
+                path.strip_prefix(&cwd)
+                    .unwrap_or(&path)
+                    .to_str()
+                    .unwrap()
+                    .replace('\\', "/"),
+                self.get_lines(&path, None),
+            );
         }
 
         let mut tested = 0;
-        for _ in res.stdout.split('\n')
-                           .filter(|s| s.starts_with("test "))
-                           .inspect(|s| {
-                               let tmp: Vec<&str> = s.split(" - ").collect();
-                               if tmp.len() == 2 {
-                                   let path = tmp[0].rsplit("test ").next().unwrap();
-                                   if let Some(ref mut v) = files.get_mut(
-                                                                &path.replace('\\', "/")) {
-                                       tested += 1;
-                                       let mut iter = tmp[1].split("(line ");
-                                       iter.next();
-                                       let line = iter.next()
-                                                      .unwrap_or(")")
-                                                      .split(')')
-                                                      .next()
-                                                      .unwrap_or("0")
-                                                      .parse()
-                                                      .unwrap_or(0);
-                                       if let Ok(pos) = v.binary_search(&line) {
-                                           v.remove(pos);
-                                       } else {
-                                           self.fatal_proc_rec(
-                                               &format!("Not found doc test: \"{}\" in \"{}\":{:?}",
-                                                        s, path, v),
-                                               &res);
-                                       }
-                                   }
-                               }
-                           }) {}
+        for _ in res.stdout
+            .split('\n')
+            .filter(|s| s.starts_with("test "))
+            .inspect(|s| {
+                let tmp: Vec<&str> = s.split(" - ").collect();
+                if tmp.len() == 2 {
+                    let path = tmp[0].rsplit("test ").next().unwrap();
+                    if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) {
+                        tested += 1;
+                        let mut iter = tmp[1].split("(line ");
+                        iter.next();
+                        let line = iter.next()
+                            .unwrap_or(")")
+                            .split(')')
+                            .next()
+                            .unwrap_or("0")
+                            .parse()
+                            .unwrap_or(0);
+                        if let Ok(pos) = v.binary_search(&line) {
+                            v.remove(pos);
+                        } else {
+                            self.fatal_proc_rec(
+                                &format!("Not found doc test: \"{}\" in \"{}\":{:?}", s, path, v),
+                                &res,
+                            );
+                        }
+                    }
+                }
+            }) {}
         if tested == 0 {
             self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res);
         } else {
             for (entry, v) in &files {
                 if !v.is_empty() {
-                    self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}",
-                                                 if v.len() > 1 { "s" } else { "" }, entry, v),
-                                        &res);
+                    self.fatal_proc_rec(
+                        &format!(
+                            "Not found test at line{} \"{}\":{:?}",
+                            if v.len() > 1 { "s" } else { "" },
+                            entry,
+                            v
+                        ),
+                        &res,
+                    );
                 }
             }
         }
@@ -1897,13 +2030,13 @@ actual:\n\
         let mut wrong_cgus = Vec::new();
 
         for expected_item in &expected {
-            let actual_item_with_same_name = actual.iter()
-                                                   .find(|ti| ti.name == expected_item.name);
+            let actual_item_with_same_name = actual.iter().find(|ti| ti.name == expected_item.name);
 
             if let Some(actual_item) = actual_item_with_same_name {
                 if !expected_item.codegen_units.is_empty() &&
                    // Also check for codegen units
-                   expected_item.codegen_units != actual_item.codegen_units {
+                   expected_item.codegen_units != actual_item.codegen_units
+                {
                     wrong_cgus.push((expected_item.clone(), actual_item.clone()));
                 }
             } else {
@@ -1911,11 +2044,11 @@ actual:\n\
             }
         }
 
-        let unexpected: Vec<_> =
-            actual.iter()
-                  .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name))
-                  .map(|acgu| acgu.string.clone())
-                  .collect();
+        let unexpected: Vec<_> = actual
+            .iter()
+            .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name))
+            .map(|acgu| acgu.string.clone())
+            .collect();
 
         if !missing.is_empty() {
             missing.sort();
@@ -1951,14 +2084,19 @@ actual:\n\
 
             for &(ref expected_item, ref actual_item) in &wrong_cgus {
                 println!("{}", expected_item.name);
-                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
-                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
+                println!(
+                    "  expected: {}",
+                    codegen_units_to_str(&expected_item.codegen_units)
+                );
+                println!(
+                    "  actual:   {}",
+                    codegen_units_to_str(&actual_item.codegen_units)
+                );
                 println!("");
             }
         }
 
-        if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty())
-        {
+        if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty()) {
             panic!();
         }
 
@@ -1980,22 +2118,22 @@ actual:\n\
             let full_string = format!("{}{}", PREFIX, s.trim().to_owned());
 
             let parts: Vec<&str> = s.split(CGU_MARKER)
-                                    .map(str::trim)
-                                    .filter(|s| !s.is_empty())
-                                    .collect();
+                .map(str::trim)
+                .filter(|s| !s.is_empty())
+                .collect();
 
             let name = parts[0].trim();
 
             let cgus = if parts.len() > 1 {
                 let cgus_str = parts[1];
 
-                cgus_str.split(' ')
-                        .map(str::trim)
-                        .filter(|s| !s.is_empty())
-                        .map(str::to_owned)
-                        .collect()
-            }
-            else {
+                cgus_str
+                    .split(' ')
+                    .map(str::trim)
+                    .filter(|s| !s.is_empty())
+                    .map(str::to_owned)
+                    .collect()
+            } else {
                 HashSet::new()
             };
 
@@ -2006,8 +2144,7 @@ actual:\n\
             }
         }
 
-        fn codegen_units_to_str(cgus: &HashSet<String>) -> String
-        {
+        fn codegen_units_to_str(cgus: &HashSet<String>) -> String {
             let mut cgus: Vec<_> = cgus.iter().collect();
             cgus.sort();
 
@@ -2038,7 +2175,10 @@ actual:\n\
         fs::create_dir_all(&incremental_dir).unwrap();
 
         if self.config.verbose {
-            print!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+            print!(
+                "init_incremental_test: incremental_dir={}",
+                incremental_dir.display()
+            );
         }
     }
 
@@ -2062,11 +2202,15 @@ actual:\n\
         // FIXME -- use non-incremental mode as an oracle? That doesn't apply
         // to #[rustc_dirty] and clean tests I guess
 
-        let revision = self.revision.expect("incremental tests require a list of revisions");
+        let revision = self.revision
+            .expect("incremental tests require a list of revisions");
 
         // Incremental workproduct directory should have already been created.
         let incremental_dir = self.incremental_dir();
-        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
+        assert!(
+            incremental_dir.exists(),
+            "init_incremental_test failed to create incremental dir"
+        );
 
         // Add an extra flag pointing at the incremental directory.
         let mut revision_props = self.props.clone();
@@ -2080,7 +2224,11 @@ actual:\n\
         };
 
         if self.config.verbose {
-            print!("revision={:?} revision_props={:#?}", revision, revision_props);
+            print!(
+                "revision={:?} revision_props={:#?}",
+                revision,
+                revision_props
+            );
         }
 
         if revision.starts_with("rpass") {
@@ -2090,8 +2238,7 @@ actual:\n\
         } else if revision.starts_with("cfail") {
             revision_cx.run_cfail_test();
         } else {
-            revision_cx.fatal(
-                "revision name must begin with rpass, rfail, or cfail");
+            revision_cx.fatal("revision name must begin with rpass, rfail, or cfail");
         }
     }
 
@@ -2103,13 +2250,18 @@ actual:\n\
     fn run_rmake_test(&self) {
         // FIXME(#11094): we should fix these tests
         if self.config.host != self.config.target {
-            return
+            return;
         }
 
         let cwd = env::current_dir().unwrap();
-        let src_root = self.config.src_base.parent().unwrap()
-                                           .parent().unwrap()
-                                           .parent().unwrap();
+        let src_root = self.config
+            .src_base
+            .parent()
+            .unwrap()
+            .parent()
+            .unwrap()
+            .parent()
+            .unwrap();
         let src_root = cwd.join(&src_root);
 
         let tmpdir = cwd.join(self.output_base_name());
@@ -2119,9 +2271,10 @@ actual:\n\
         create_dir_all(&tmpdir).unwrap();
 
         let host = &self.config.host;
-        let make = if host.contains("bitrig") || host.contains("dragonfly") ||
-            host.contains("freebsd") || host.contains("netbsd") ||
-            host.contains("openbsd") {
+        let make = if host.contains("bitrig") || host.contains("dragonfly")
+            || host.contains("freebsd") || host.contains("netbsd")
+            || host.contains("openbsd")
+        {
             "gmake"
         } else {
             "make"
@@ -2129,21 +2282,26 @@ actual:\n\
 
         let mut cmd = Command::new(make);
         cmd.current_dir(&self.testpaths.file)
-           .stdout(Stdio::piped())
-           .stderr(Stdio::piped())
-           .env("TARGET", &self.config.target)
-           .env("PYTHON", &self.config.docck_python)
-           .env("S", src_root)
-           .env("RUST_BUILD_STAGE", &self.config.stage_id)
-           .env("RUSTC", cwd.join(&self.config.rustc_path))
-           .env("RUSTDOC",
-               cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed")))
-           .env("TMPDIR", &tmpdir)
-           .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-           .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
-           .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-           .env("LLVM_COMPONENTS", &self.config.llvm_components)
-           .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags);
+            .stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            .env("TARGET", &self.config.target)
+            .env("PYTHON", &self.config.docck_python)
+            .env("S", src_root)
+            .env("RUST_BUILD_STAGE", &self.config.stage_id)
+            .env("RUSTC", cwd.join(&self.config.rustc_path))
+            .env(
+                "RUSTDOC",
+                cwd.join(&self.config
+                    .rustdoc_path
+                    .as_ref()
+                    .expect("--rustdoc-path passed")),
+            )
+            .env("TMPDIR", &tmpdir)
+            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
+            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
+            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
+            .env("LLVM_COMPONENTS", &self.config.llvm_components)
+            .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags);
 
         if let Some(ref linker) = self.config.linker {
             cmd.env("RUSTC_LINKER", linker);
@@ -2161,25 +2319,31 @@ actual:\n\
             // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
             // a path and instead passes `C:\msys64\foo`, so convert all
             // `/`-arguments to MSVC here to `-` arguments.
-            let cflags = self.config.cflags.split(' ').map(|s| s.replace("/", "-"))
-                                                 .collect::<Vec<_>>().join(" ");
+            let cflags = self.config
+                .cflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
 
             cmd.env("IS_MSVC", "1")
-               .env("IS_WINDOWS", "1")
-               .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
-               .env("CC", format!("'{}' {}", self.config.cc, cflags))
-               .env("CXX", &self.config.cxx);
+                .env("IS_WINDOWS", "1")
+                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
+                .env("CC", format!("'{}' {}", self.config.cc, cflags))
+                .env("CXX", &self.config.cxx);
         } else {
             cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-               .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
-               .env("AR", &self.config.ar);
+                .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
+                .env("AR", &self.config.ar);
 
             if self.config.target.contains("windows") {
                 cmd.env("IS_WINDOWS", "1");
             }
         }
 
-        let output = cmd.spawn().and_then(read2_abbreviated).expect("failed to spawn `make`");
+        let output = cmd.spawn()
+            .and_then(read2_abbreviated)
+            .expect("failed to spawn `make`");
         if !output.status.success() {
             let res = ProcRes {
                 status: output.status,
@@ -2218,14 +2382,17 @@ actual:\n\
         // if the user specified a format in the ui test
         // print the output to the stderr file, otherwise extract
         // the rendered error messages from json and print them
-        let explicit = self.props.compile_flags.iter().any(|s| s.contains("--error-format"));
+        let explicit = self.props
+            .compile_flags
+            .iter()
+            .any(|s| s.contains("--error-format"));
 
         let proc_res = self.compile_test();
 
-        let expected_stderr_path = self.expected_output_path("stderr");
+        let expected_stderr_path = self.expected_output_path(UI_STDERR);
         let expected_stderr = self.load_expected_output(&expected_stderr_path);
 
-        let expected_stdout_path = self.expected_output_path("stdout");
+        let expected_stdout_path = self.expected_output_path(UI_STDOUT);
         let expected_stdout = self.load_expected_output(&expected_stdout_path);
 
         let normalized_stdout =
@@ -2237,8 +2404,7 @@ actual:\n\
             json::extract_rendered(&proc_res.stderr, &proc_res)
         };
 
-        let normalized_stderr =
-            self.normalize_output(&stderr, &self.props.normalize_stderr);
+        let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr);
 
         let mut errors = 0;
         errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout);
@@ -2246,15 +2412,19 @@ actual:\n\
 
         if errors > 0 {
             println!("To update references, run this command from build directory:");
-            let relative_path_to_file =
-                self.testpaths.relative_dir
-                              .join(self.testpaths.file.file_name().unwrap());
-            println!("{}/update-references.sh '{}' '{}'",
-                     self.config.src_base.display(),
-                     self.config.build_base.display(),
-                     relative_path_to_file.display());
-            self.fatal_proc_rec(&format!("{} errors occurred comparing output.", errors),
-                                &proc_res);
+            let relative_path_to_file = self.testpaths
+                .relative_dir
+                .join(self.testpaths.file.file_name().unwrap());
+            println!(
+                "{}/update-references.sh '{}' '{}'",
+                self.config.src_base.display(),
+                self.config.build_base.display(),
+                relative_path_to_file.display()
+            );
+            self.fatal_proc_rec(
+                &format!("{} errors occurred comparing output.", errors),
+                &proc_res,
+            );
         }
 
         let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
@@ -2294,13 +2464,14 @@ actual:\n\
 
     fn check_mir_dump(&self) {
         let mut test_file_contents = String::new();
-        fs::File::open(self.testpaths.file.clone()).unwrap()
-                                                   .read_to_string(&mut test_file_contents)
-                                                   .unwrap();
-        if let Some(idx) =  test_file_contents.find("// END RUST SOURCE") {
+        fs::File::open(self.testpaths.file.clone())
+            .unwrap()
+            .read_to_string(&mut test_file_contents)
+            .unwrap();
+        if let Some(idx) = test_file_contents.find("// END RUST SOURCE") {
             let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
             let tests_text_str = String::from(tests_text);
-            let mut curr_test : Option<&str> = None;
+            let mut curr_test: Option<&str> = None;
             let mut curr_test_contents = vec![ExpectedLine::Elision];
             for l in tests_text_str.lines() {
                 debug!("line: {:?}", l);
@@ -2334,9 +2505,16 @@ actual:\n\
         let output_time = t(output_file);
         let source_time = t(source_file);
         if source_time > output_time {
-            debug!("source file time: {:?} output file time: {:?}", source_time, output_time);
-            panic!("test source file `{}` is newer than potentially stale output file `{}`.",
-                   source_file.display(), test_name);
+            debug!(
+                "source file time: {:?} output file time: {:?}",
+                source_time,
+                output_time
+            );
+            panic!(
+                "test source file `{}` is newer than potentially stale output file `{}`.",
+                source_file.display(),
+                test_name
+            );
         }
     }
 
@@ -2347,22 +2525,30 @@ actual:\n\
         debug!("comparing the contests of: {:?}", output_file);
         debug!("with: {:?}", expected_content);
         if !output_file.exists() {
-            panic!("Output file `{}` from test does not exist",
-                   output_file.into_os_string().to_string_lossy());
+            panic!(
+                "Output file `{}` from test does not exist",
+                output_file.into_os_string().to_string_lossy()
+            );
         }
         self.check_mir_test_timestamp(test_name, &output_file);
 
         let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
         let mut dumped_string = String::new();
         dumped_file.read_to_string(&mut dumped_string).unwrap();
-        let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty());
-        let mut expected_lines = expected_content.iter().filter(|&l| {
-            if let &ExpectedLine::Text(l) = l {
-                !l.is_empty()
-            } else {
-                true
-            }
-        }).peekable();
+        let mut dumped_lines = dumped_string
+            .lines()
+            .map(|l| nocomment_mir_line(l))
+            .filter(|l| !l.is_empty());
+        let mut expected_lines = expected_content
+            .iter()
+            .filter(|&l| {
+                if let &ExpectedLine::Text(l) = l {
+                    !l.is_empty()
+                } else {
+                    true
+                }
+            })
+            .peekable();
 
         let compare = |expected_line, dumped_line| {
             let e_norm = normalize_mir_line(expected_line);
@@ -2373,27 +2559,31 @@ actual:\n\
         };
 
         let error = |expected_line, extra_msg| {
-            let normalize_all = dumped_string.lines()
-                                             .map(nocomment_mir_line)
-                                             .filter(|l| !l.is_empty())
-                                             .collect::<Vec<_>>()
-                                             .join("\n");
+            let normalize_all = dumped_string
+                .lines()
+                .map(nocomment_mir_line)
+                .filter(|l| !l.is_empty())
+                .collect::<Vec<_>>()
+                .join("\n");
             let f = |l: &ExpectedLine<_>| match l {
                 &ExpectedLine::Elision => "... (elided)".into(),
-                &ExpectedLine::Text(t) => t
+                &ExpectedLine::Text(t) => t,
             };
-            let expected_content = expected_content.iter()
-                                                   .map(|l| f(l))
-                                                   .collect::<Vec<_>>()
-                                                   .join("\n");
-            panic!("Did not find expected line, error: {}\n\
-                   Actual Line: {:?}\n\
-                   Expected:\n{}\n\
-                   Actual:\n{}",
-                   extra_msg,
-                   expected_line,
-                   expected_content,
-                   normalize_all);
+            let expected_content = expected_content
+                .iter()
+                .map(|l| f(l))
+                .collect::<Vec<_>>()
+                .join("\n");
+            panic!(
+                "Did not find expected line, error: {}\n\
+                 Expected Line: {:?}\n\
+                 Expected:\n{}\n\
+                 Actual:\n{}",
+                extra_msg,
+                expected_line,
+                expected_content,
+                normalize_all
+            );
         };
 
         // We expect each non-empty line to appear consecutively, non-consecutive lines
@@ -2409,11 +2599,18 @@ actual:\n\
 
                     if !compare(expected_line, dumped_line) {
                         error!("{:?}", start_block_line);
-                        error(expected_line,
-                              format!("Mismatch in lines\nCurrnt block: {}\nExpected Line: {:?}",
-                                      start_block_line.unwrap_or("None"), dumped_line));
+                        error(
+                            expected_line,
+                            format!(
+                                "Mismatch in lines\n\
+                                 Current block: {}\n\
+                                 Actual Line: {:?}",
+                                start_block_line.unwrap_or("None"),
+                                dumped_line
+                            ),
+                        );
                     }
-                },
+                }
                 Some(&ExpectedLine::Elision) => {
                     // skip any number of elisions in a row.
                     while let Some(&&ExpectedLine::Elision) = expected_lines.peek() {
@@ -2434,8 +2631,8 @@ actual:\n\
                             error(expected_line, "ran out of mir dump to match against".into());
                         }
                     }
-                },
-                None => {},
+                }
+                None => {}
             }
         }
     }
@@ -2451,10 +2648,10 @@ actual:\n\
     fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
         let parent_dir = self.testpaths.file.parent().unwrap();
         let cflags = self.props.compile_flags.join(" ");
-        let json = cflags.contains("--error-format json") ||
-                   cflags.contains("--error-format pretty-json") ||
-                   cflags.contains("--error-format=json") ||
-                   cflags.contains("--error-format=pretty-json");
+        let json = cflags.contains("--error-format json")
+            || cflags.contains("--error-format pretty-json")
+            || cflags.contains("--error-format=json")
+            || cflags.contains("--error-format=pretty-json");
         let parent_dir_str = if json {
             parent_dir.display().to_string().replace("\\", "\\\\")
         } else {
@@ -2482,11 +2679,7 @@ actual:\n\
     }
 
     fn expected_output_path(&self, kind: &str) -> PathBuf {
-        let extension = match self.revision {
-            Some(r) => format!("{}.{}", r, kind),
-            None => kind.to_string(),
-        };
-        self.testpaths.file.with_extension(extension)
+        expected_output_path(&self.testpaths, self.revision, kind)
     }
 
     fn load_expected_output(&self, path: &Path) -> String {
@@ -2497,10 +2690,11 @@ actual:\n\
         let mut result = String::new();
         match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) {
             Ok(_) => result,
-            Err(e) => {
-                self.fatal(&format!("failed to load expected output from `{}`: {}",
-                                    path.display(), e))
-            }
+            Err(e) => self.fatal(&format!(
+                "failed to load expected output from `{}`: {}",
+                path.display(),
+                e
+            )),
         }
     }
 
@@ -2515,19 +2709,21 @@ actual:\n\
 
         for diff in diff::lines(expected, actual) {
             match diff {
-                diff::Result::Left(l)    => println!("-{}", l),
+                diff::Result::Left(l) => println!("-{}", l),
                 diff::Result::Both(l, _) => println!(" {}", l),
-                diff::Result::Right(r)   => println!("+{}", r),
+                diff::Result::Right(r) => println!("+{}", r),
             }
         }
 
         let output_file = self.output_base_name().with_extension(kind);
         match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
-            Ok(()) => { }
-            Err(e) => {
-                self.fatal(&format!("failed to write {} to `{}`: {}",
-                                    kind, output_file.display(), e))
-            }
+            Ok(()) => {}
+            Err(e) => self.fatal(&format!(
+                "failed to write {} to `{}`: {}",
+                kind,
+                output_file.display(),
+                e
+            )),
         }
 
         println!("\nThe actual {0} differed from the expected {0}.", kind);
@@ -2553,20 +2749,24 @@ impl ProcRes {
         if let Some(e) = err {
             println!("\nerror: {}", e);
         }
-        print!("\
-            status: {}\n\
-            command: {}\n\
-            stdout:\n\
-            ------------------------------------------\n\
-            {}\n\
-            ------------------------------------------\n\
-            stderr:\n\
-            ------------------------------------------\n\
-            {}\n\
-            ------------------------------------------\n\
-            \n",
-               self.status, self.cmdline, self.stdout,
-               self.stderr);
+        print!(
+            "\
+             status: {}\n\
+             command: {}\n\
+             stdout:\n\
+             ------------------------------------------\n\
+             {}\n\
+             ------------------------------------------\n\
+             stderr:\n\
+             ------------------------------------------\n\
+             {}\n\
+             ------------------------------------------\n\
+             \n",
+            self.status,
+            self.cmdline,
+            self.stdout,
+            self.stderr
+        );
         panic!();
     }
 }
@@ -2579,12 +2779,12 @@ enum TargetLocation {
 #[derive(Clone, PartialEq, Eq)]
 enum ExpectedLine<T: AsRef<str>> {
     Elision,
-    Text(T)
+    Text(T),
 }
 
 impl<T> fmt::Debug for ExpectedLine<T>
 where
-    T: AsRef<str> + fmt::Debug
+    T: AsRef<str> + fmt::Debug,
 {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         if let &ExpectedLine::Text(ref t) = self {
@@ -2621,7 +2821,7 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
             head: Vec<u8>,
             skipped: usize,
             tail: Box<[u8]>,
-        }
+        },
     }
 
     impl ProcOutput {
@@ -2636,9 +2836,17 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
                     let tail = bytes.split_off(new_len - TAIL_LEN).into_boxed_slice();
                     let head = replace(bytes, Vec::new());
                     let skipped = new_len - HEAD_LEN - TAIL_LEN;
-                    ProcOutput::Abbreviated { head, skipped, tail }
+                    ProcOutput::Abbreviated {
+                        head,
+                        skipped,
+                        tail,
+                    }
                 }
-                ProcOutput::Abbreviated { ref mut skipped, ref mut tail, .. } => {
+                ProcOutput::Abbreviated {
+                    ref mut skipped,
+                    ref mut tail,
+                    ..
+                } => {
                     *skipped += data.len();
                     if data.len() <= TAIL_LEN {
                         tail[..data.len()].copy_from_slice(data);
@@ -2655,7 +2863,11 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
         fn into_bytes(self) -> Vec<u8> {
             match self {
                 ProcOutput::Full(bytes) => bytes,
-                ProcOutput::Abbreviated { mut head, skipped, tail } => {
+                ProcOutput::Abbreviated {
+                    mut head,
+                    skipped,
+                    tail,
+                } => {
                     write!(&mut head, "\n\n<<<<<< SKIPPED {} BYTES >>>>>>\n\n", skipped).unwrap();
                     head.extend_from_slice(&tail);
                     head
@@ -2668,10 +2880,14 @@ fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
     let mut stderr = ProcOutput::Full(Vec::new());
 
     drop(child.stdin.take());
-    read2(child.stdout.take().unwrap(), child.stderr.take().unwrap(), &mut |is_stdout, data, _| {
-        if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
-        data.clear();
-    })?;
+    read2(
+        child.stdout.take().unwrap(),
+        child.stderr.take().unwrap(),
+        &mut |is_stdout, data, _| {
+            if is_stdout { &mut stdout } else { &mut stderr }.extend(data);
+            data.clear();
+        },
+    )?;
     let status = child.wait()?;
 
     Ok(Output {
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 9736c039930..eca225ee8a8 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -89,7 +89,9 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
 
     let mut contents = String::new();
 
-    super::walk_many(&[&path.join("test/compile-fail"),
+    super::walk_many(&[&path.join("test/ui-fulldeps"),
+                       &path.join("test/ui"),
+                       &path.join("test/compile-fail"),
                        &path.join("test/compile-fail-fulldeps"),
                        &path.join("test/parse-fail"),],
                      &mut |path| super::filter_dirs(path),
@@ -150,9 +152,9 @@ pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
 
     for &(name, _) in gate_untested.iter() {
         println!("Expected a gate test for the feature '{}'.", name);
-        println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\
-                \n      test suite, with its failures due to missing usage of\
-                \n      #![feature({})].", name, name);
+        println!("Hint: create a failing test file named 'feature-gate-{}.rs'\
+                \n      in the 'ui' test suite, with its failures due to\
+                \n      missing usage of #![feature({})].", name, name);
         println!("Hint: If you already have such a test and don't want to rename it,\
                 \n      you can also add a // gate-test-{} line to the test file.",
                  name);