about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Cargo.lock51
-rw-r--r--src/bootstrap/install.rs25
-rw-r--r--src/bootstrap/native.rs4
-rw-r--r--src/bootstrap/tool.rs3
-rwxr-xr-xsrc/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh6
-rw-r--r--src/doc/not_found.md2
-rw-r--r--src/doc/unstable-book/src/language-features/non-exhaustive.md75
-rw-r--r--src/doc/unstable-book/src/language-features/optin-builtin-traits.md4
-rw-r--r--src/etc/char_private.py4
-rw-r--r--src/liballoc/benches/str.rs3
-rw-r--r--src/liballoc/borrow.rs1
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/raw_vec.rs2
-rw-r--r--src/liballoc/slice.rs211
-rw-r--r--src/liballoc/str.rs284
-rw-r--r--src/liballoc/string.rs2
-rw-r--r--src/liballoc/tests/str.rs1
-rw-r--r--src/liballoc/tests/vec.rs3
-rw-r--r--src/liballoc/vec.rs2
-rw-r--r--src/liballoc_jemalloc/lib.rs28
-rwxr-xr-xsrc/libbacktrace/configure6
-rw-r--r--src/libbacktrace/configure.ac6
-rw-r--r--src/libcore/char_private.rs157
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/marker.rs6
-rw-r--r--src/libcore/num/mod.rs648
-rw-r--r--src/libcore/ops/deref.rs4
-rw-r--r--src/libcore/ptr.rs18
-rw-r--r--src/libcore/slice/mod.rs16
-rw-r--r--src/libcore/sync/atomic.rs12
-rw-r--r--src/libcore/tests/ptr.rs51
-rw-r--r--src/libcore/unit.rs31
-rw-r--r--src/librustc/dep_graph/dep_node.rs84
-rw-r--r--src/librustc/dep_graph/graph.rs179
-rw-r--r--src/librustc/dep_graph/mod.rs2
-rw-r--r--src/librustc/hir/def_id.rs69
-rw-r--r--src/librustc/hir/intravisit.rs4
-rw-r--r--src/librustc/hir/lowering.rs31
-rw-r--r--src/librustc/hir/map/collector.rs2
-rw-r--r--src/librustc/hir/map/def_collector.rs2
-rw-r--r--src/librustc/hir/map/definitions.rs2
-rw-r--r--src/librustc/hir/map/mod.rs20
-rw-r--r--src/librustc/hir/mod.rs19
-rw-r--r--src/librustc/hir/print.rs21
-rw-r--r--src/librustc/ich/fingerprint.rs5
-rw-r--r--src/librustc/ich/hcx.rs4
-rw-r--r--src/librustc/ich/impls_hir.rs38
-rw-r--r--src/librustc/ich/impls_mir.rs9
-rw-r--r--src/librustc/ich/impls_syntax.rs16
-rw-r--r--src/librustc/ich/impls_ty.rs10
-rw-r--r--src/librustc/infer/README.md2
-rw-r--r--src/librustc/infer/error_reporting/different_lifetimes.rs55
-rw-r--r--src/librustc/infer/error_reporting/mod.rs74
-rw-r--r--src/librustc/infer/error_reporting/named_anon_conflict.rs16
-rw-r--r--src/librustc/infer/error_reporting/util.rs1
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs5
-rw-r--r--src/librustc/infer/region_inference/graphviz.rs1
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/mod.rs5
-rw-r--r--src/librustc/middle/cstore.rs4
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/middle/free_region.rs13
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/region.rs4
-rw-r--r--src/librustc/middle/resolve_lifetime.rs14
-rw-r--r--src/librustc/mir/mod.rs51
-rw-r--r--src/librustc/mir/transform.rs6
-rw-r--r--src/librustc/mir/visit.rs58
-rw-r--r--src/librustc/session/config.rs187
-rw-r--r--src/librustc/session/mod.rs39
-rw-r--r--src/librustc/traits/mod.rs14
-rw-r--r--src/librustc/traits/project.rs4
-rw-r--r--src/librustc/traits/select.rs52
-rw-r--r--src/librustc/traits/structural_impls.rs16
-rw-r--r--src/librustc/traits/trans/mod.rs54
-rw-r--r--src/librustc/ty/codec.rs243
-rw-r--r--src/librustc/ty/context.rs16
-rw-r--r--src/librustc/ty/fold.rs37
-rw-r--r--src/librustc/ty/instance.rs4
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/maps/mod.rs7
-rw-r--r--src/librustc/ty/maps/on_disk_cache.rs231
-rw-r--r--src/librustc/ty/maps/plumbing.rs92
-rw-r--r--src/librustc/ty/mod.rs22
-rw-r--r--src/librustc/ty/trait_def.rs6
-rw-r--r--src/librustc_allocator/expand.rs4
-rw-r--r--src/librustc_apfloat/lib.rs4
-rw-r--r--src/librustc_back/target/mod.rs6
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs3
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs13
-rw-r--r--src/librustc_const_eval/_match.rs73
-rw-r--r--src/librustc_const_math/float.rs8
-rw-r--r--src/librustc_data_structures/bitvec.rs36
-rw-r--r--src/librustc_data_structures/indexed_set.rs12
-rw-r--r--src/librustc_data_structures/indexed_vec.rs266
-rw-r--r--src/librustc_data_structures/transitive_relation.rs4
-rw-r--r--src/librustc_driver/driver.rs6
-rw-r--r--src/librustc_driver/lib.rs8
-rw-r--r--src/librustc_driver/test.rs4
-rw-r--r--src/librustc_errors/diagnostic.rs12
-rw-r--r--src/librustc_errors/diagnostic_builder.rs5
-rw-r--r--src/librustc_errors/emitter.rs32
-rw-r--r--src/librustc_errors/lib.rs32
-rw-r--r--src/librustc_incremental/lib.rs6
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs2
-rw-r--r--src/librustc_incremental/persist/fs.rs5
-rw-r--r--src/librustc_incremental/persist/load.rs13
-rw-r--r--src/librustc_incremental/persist/mod.rs3
-rw-r--r--src/librustc_incremental/persist/save.rs12
-rw-r--r--src/librustc_lint/bad_style.rs6
-rw-r--r--src/librustc_lint/builtin.rs84
-rw-r--r--src/librustc_lint/lib.rs6
-rw-r--r--src/librustc_llvm/ffi.rs12
-rw-r--r--src/librustc_llvm/lib.rs5
-rw-r--r--src/librustc_metadata/creader.rs30
-rw-r--r--src/librustc_metadata/cstore.rs38
-rw-r--r--src/librustc_metadata/cstore_impl.rs32
-rw-r--r--src/librustc_metadata/decoder.rs187
-rw-r--r--src/librustc_metadata/encoder.rs75
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_metadata/schema.rs13
-rw-r--r--src/librustc_mir/borrow_check.rs253
-rw-r--r--src/librustc_mir/build/matches/mod.rs118
-rw-r--r--src/librustc_mir/build/matches/test.rs4
-rw-r--r--src/librustc_mir/build/mod.rs12
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs48
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs69
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs66
-rw-r--r--src/librustc_mir/dataflow/mod.rs30
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs39
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs6
-rw-r--r--src/librustc_mir/lib.rs3
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs3
-rw-r--r--src/librustc_mir/transform/clean_end_regions.rs4
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs10
-rw-r--r--src/librustc_mir/transform/erase_regions.rs4
-rw-r--r--src/librustc_mir/transform/generator.rs7
-rw-r--r--src/librustc_mir/transform/inline.rs6
-rw-r--r--src/librustc_mir/transform/nll/constraint_generation.rs274
-rw-r--r--src/librustc_mir/transform/nll/free_regions.rs88
-rw-r--r--src/librustc_mir/transform/nll/infer.rs222
-rw-r--r--src/librustc_mir/transform/nll/mod.rs319
-rw-r--r--src/librustc_mir/transform/nll/region_infer.rs400
-rw-r--r--src/librustc_mir/transform/nll/renumber.rs182
-rw-r--r--src/librustc_mir/transform/nll/subtype.rs99
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs3
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs3
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs3
-rw-r--r--src/librustc_mir/transform/type_check.rs13
-rw-r--r--src/librustc_mir/util/borrowck_errors.rs46
-rw-r--r--src/librustc_mir/util/graphviz.rs26
-rw-r--r--src/librustc_mir/util/liveness.rs386
-rw-r--r--src/librustc_mir/util/pretty.rs68
-rw-r--r--src/librustc_passes/ast_validation.rs29
-rw-r--r--src/librustc_passes/mir_stats.rs6
-rw-r--r--src/librustc_privacy/lib.rs18
-rw-r--r--src/librustc_resolve/Cargo.toml1
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs18
-rw-r--r--src/librustc_resolve/lib.rs20
-rw-r--r--src/librustc_resolve/macros.rs1
-rw-r--r--src/librustc_save_analysis/Cargo.toml2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs175
-rw-r--r--src/librustc_save_analysis/lib.rs119
-rw-r--r--src/librustc_save_analysis/sig.rs9
-rw-r--r--src/librustc_save_analysis/span_utils.rs43
-rw-r--r--src/librustc_trans/Cargo.toml1
-rw-r--r--src/librustc_trans/back/link.rs2
-rw-r--r--src/librustc_trans/back/symbol_export.rs24
-rw-r--r--src/librustc_trans/back/write.rs17
-rw-r--r--src/librustc_trans/consts.rs9
-rw-r--r--src/librustc_trans/context.rs30
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustc_trans/mir/analyze.rs3
-rw-r--r--src/librustc_trans/mir/block.rs3
-rw-r--r--src/librustc_trans/mir/constant.rs73
-rw-r--r--src/librustc_trans/mir/rvalue.rs169
-rw-r--r--src/librustc_trans/partitioning.rs14
-rw-r--r--src/librustc_trans_utils/collector.rs39
-rw-r--r--src/librustc_trans_utils/common.rs3
-rw-r--r--src/librustc_trans_utils/lib.rs9
-rw-r--r--src/librustc_typeck/README.md2
-rw-r--r--src/librustc_typeck/astconv.rs54
-rw-r--r--src/librustc_typeck/check/_match.rs41
-rw-r--r--src/librustc_typeck/check/cast.rs82
-rw-r--r--src/librustc_typeck/check/closure.rs483
-rw-r--r--src/librustc_typeck/check/method/probe.rs3
-rw-r--r--src/librustc_typeck/check/mod.rs13
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs7
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/coherence/orphan.rs8
-rw-r--r--src/librustc_typeck/coherence/overlap.rs10
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs2
-rw-r--r--src/librustc_typeck/collect.rs31
-rw-r--r--src/librustc_typeck/diagnostics.rs64
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustdoc/clean/cfg.rs1
-rw-r--r--src/librustdoc/clean/inline.rs6
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/doctree.rs4
-rw-r--r--src/librustdoc/html/item_type.rs2
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/markdown.rs1
-rw-r--r--src/librustdoc/html/render.rs183
-rw-r--r--src/librustdoc/html/static/main.js155
-rw-r--r--src/librustdoc/html/static/rustdoc.css3
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/librustdoc/passes/mod.rs2
-rw-r--r--src/librustdoc/test.rs16
-rw-r--r--src/librustdoc/visit_ast.rs6
-rw-r--r--src/libstd/Cargo.toml3
-rw-r--r--src/libstd/ascii.rs712
-rw-r--r--src/libstd/env.rs4
-rw-r--r--src/libstd/heap.rs11
-rw-r--r--src/libstd/io/buffered.rs25
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/panic.rs4
-rw-r--r--src/libstd/path.rs1
-rw-r--r--src/libstd/sync/rwlock.rs11
-rw-r--r--src/libstd/sys/unix/ext/fs.rs320
-rw-r--r--src/libstd/sys/windows/c.rs4
-rw-r--r--src/libstd/sys/windows/path.rs2
-rw-r--r--src/libstd/sys/windows/process.rs2
-rw-r--r--src/libstd/thread/mod.rs14
-rw-r--r--src/libstd_unicode/char.rs523
-rw-r--r--src/libstd_unicode/lib.rs1
-rw-r--r--src/libsyntax/ast.rs15
-rw-r--r--src/libsyntax/codemap.rs79
-rw-r--r--src/libsyntax/diagnostics/macros.rs65
-rw-r--r--src/libsyntax/feature_gate.rs26
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/json.rs38
-rw-r--r--src/libsyntax/parse/lexer/mod.rs1
-rw-r--r--src/libsyntax/parse/parser.rs187
-rw-r--r--src/libsyntax/print/pprust.rs21
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/libsyntax_pos/Cargo.toml1
-rw-r--r--src/libsyntax_pos/lib.rs95
-rw-r--r--src/libsyntax_pos/span_encoding.rs8
-rw-r--r--src/libsyntax_pos/symbol.rs11
-rw-r--r--src/rtstartup/rsbegin.rs6
-rw-r--r--src/rtstartup/rsend.rs2
-rw-r--r--src/test/codegen-units/item-collection/unreferenced-const-fn.rs22
-rw-r--r--src/test/codegen-units/item-collection/unreferenced-inline-function.rs23
-rw-r--r--src/test/codegen-units/partitioning/extern-drop-glue.rs12
-rw-r--r--src/test/codegen-units/partitioning/inlining-from-extern-crate.rs8
-rw-r--r--src/test/codegen-units/partitioning/local-drop-glue.rs12
-rw-r--r--src/test/codegen-units/partitioning/local-inlining-but-not-all.rs18
-rw-r--r--src/test/codegen-units/partitioning/local-inlining.rs18
-rw-r--r--src/test/codegen-units/partitioning/local-transitive-inlining.rs14
-rw-r--r--src/test/codegen-units/partitioning/statics.rs12
-rw-r--r--src/test/codegen/adjustments.rs2
-rw-r--r--src/test/codegen/fastcall-inreg.rs14
-rw-r--r--src/test/codegen/function-arguments.rs14
-rw-r--r--src/test/codegen/mir_zst_stores.rs2
-rw-r--r--src/test/codegen/naked-functions.rs20
-rw-r--r--src/test/codegen/refs.rs2
-rw-r--r--src/test/codegen/unchecked-float-casts.rs65
-rw-r--r--src/test/compile-fail/E0029.rs1
-rw-r--r--src/test/compile-fail/E0534.rs4
-rw-r--r--src/test/compile-fail/auto-impl-future-compat.rs16
-rw-r--r--src/test/compile-fail/auto-trait-validation.rs22
-rw-r--r--src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs1
-rw-r--r--src/test/compile-fail/bad-intrinsic-monomorphization.rs11
-rw-r--r--src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs24
-rw-r--r--src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs18
-rw-r--r--src/test/compile-fail/closure-expected-type/README.md1
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs49
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs70
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs35
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs29
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs29
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs80
-rw-r--r--src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs29
-rw-r--r--src/test/compile-fail/coherence-default-trait-impl.rs6
-rw-r--r--src/test/compile-fail/dupe-symbols-2.rs4
-rw-r--r--src/test/compile-fail/feature-gate-match_default_bindings.rs3
-rw-r--r--src/test/compile-fail/feature-gate-non_exhaustive.rs20
-rw-r--r--src/test/compile-fail/feature-gate-optin-builtin-traits.rs6
-rw-r--r--src/test/compile-fail/float-int-invalid-const-cast.rs61
-rw-r--r--src/test/compile-fail/invalid-inline.rs6
-rw-r--r--src/test/compile-fail/issue-16338.rs3
-rw-r--r--src/test/compile-fail/issue-20261.rs3
-rw-r--r--src/test/compile-fail/issue-22638.rs3
-rw-r--r--src/test/compile-fail/issue-23080-2.rs1
-rw-r--r--src/test/compile-fail/issue-23080.rs1
-rw-r--r--src/test/compile-fail/keyword-false-as-identifier.rs2
-rw-r--r--src/test/compile-fail/keyword-self-as-identifier.rs2
-rw-r--r--src/test/compile-fail/keyword-super-as-identifier.rs2
-rw-r--r--src/test/compile-fail/keyword-true-as-identifier.rs2
-rw-r--r--src/test/compile-fail/match-range-fail.rs2
-rw-r--r--src/test/compile-fail/match-vec-mismatch.rs2
-rw-r--r--src/test/compile-fail/nll/loan_ends_mid_block_pair.rs50
-rw-r--r--src/test/compile-fail/nll/loan_ends_mid_block_vec.rs49
-rw-r--r--src/test/compile-fail/nll/region-ends-after-if-condition.rs46
-rw-r--r--src/test/compile-fail/nll/return_from_loop.rs49
-rw-r--r--src/test/compile-fail/non-interger-atomic.rs41
-rw-r--r--src/test/compile-fail/pat-slice-old-style.rs5
-rw-r--r--src/test/compile-fail/phantom-oibit.rs1
-rw-r--r--src/test/compile-fail/privacy-sanity.rs3
-rw-r--r--src/test/compile-fail/regions-infer-at-fn-not-param.rs2
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs19
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs37
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs18
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs25
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs47
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs36
-rw-r--r--src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs27
-rw-r--r--src/test/compile-fail/self-vs-path-ambiguity.rs1
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs3
-rw-r--r--src/test/compile-fail/specialization/specialization-polarity.rs2
-rw-r--r--src/test/compile-fail/syntaxt-default-trait-impls.rs7
-rw-r--r--src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs1
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs1
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-supertraits.rs1
-rw-r--r--src/test/compile-fail/typeck-auto-trait-no-typeparams.rs1
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs1
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs1
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-negation.rs2
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs1
-rw-r--r--src/test/compile-fail/typeck-default-trait-impl-precedence.rs1
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs37
-rw-r--r--src/test/incremental/change_add_field/struct_point.rs69
-rw-r--r--src/test/incremental/change_private_fn/struct_point.rs45
-rw-r--r--src/test/incremental/change_private_fn_cc/auxiliary/point.rs4
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs37
-rw-r--r--src/test/incremental/change_private_impl_method/struct_point.rs47
-rw-r--r--src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs4
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs37
-rw-r--r--src/test/incremental/change_pub_inherent_method_body/struct_point.rs45
-rw-r--r--src/test/incremental/change_pub_inherent_method_sig/struct_point.rs45
-rw-r--r--src/test/incremental/hashes/call_expressions.rs2
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs68
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs18
-rw-r--r--src/test/incremental/hashes/panic_exprs.rs39
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs44
-rw-r--r--src/test/incremental/hashes/trait_defs.rs4
-rw-r--r--src/test/incremental/ich_nested_items.rs36
-rw-r--r--src/test/incremental/issue-38222.rs7
-rw-r--r--src/test/incremental/krate-inherent.rs20
-rw-r--r--src/test/incremental/krate-inlined.rs4
-rw-r--r--src/test/incremental/remove_source_file/main.rs15
-rw-r--r--src/test/incremental/spans_in_type_debuginfo.rs1
-rw-r--r--src/test/incremental/string_constant.rs27
-rw-r--r--src/test/incremental/warnings-reemitted.rs19
-rw-r--r--src/test/mir-opt/copy_propagation.rs5
-rw-r--r--src/test/mir-opt/deaggregator_test.rs5
-rw-r--r--src/test/mir-opt/deaggregator_test_enum_2.rs5
-rw-r--r--src/test/mir-opt/deaggregator_test_multiple.rs5
-rw-r--r--src/test/mir-opt/end_region_destruction_extents_1.rs4
-rw-r--r--src/test/mir-opt/issue-41110.rs2
-rw-r--r--src/test/mir-opt/match_false_edges.rs240
-rw-r--r--src/test/mir-opt/nll/liveness-call-subtlety.rs51
-rw-r--r--src/test/mir-opt/nll/liveness-drop-intra-block.rs41
-rw-r--r--src/test/mir-opt/nll/liveness-interblock.rs50
-rw-r--r--src/test/mir-opt/nll/named-lifetimes-basic.rs34
-rw-r--r--src/test/mir-opt/nll/reborrow-basic.rs39
-rw-r--r--src/test/mir-opt/nll/region-liveness-basic.rs56
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs48
-rw-r--r--src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs50
-rw-r--r--src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs49
-rw-r--r--src/test/mir-opt/nll/region-subtyping-basic.rs49
-rw-r--r--src/test/mir-opt/validate_1.rs2
-rw-r--r--src/test/mir-opt/validate_4.rs4
-rw-r--r--src/test/mir-opt/validate_5.rs2
-rw-r--r--src/test/parse-fail/issue-33413.rs1
-rw-r--r--src/test/pretty/auto-trait.rs (renamed from src/test/pretty/default-trait-impl.rs)4
-rw-r--r--src/test/pretty/cast-lt.pp24
-rw-r--r--src/test/pretty/cast-lt.rs22
-rw-r--r--src/test/run-make/cdylib-fewer-symbols/Makefile17
-rw-r--r--src/test/run-make/cdylib-fewer-symbols/foo.rs16
-rw-r--r--src/test/run-make/extra-filename-with-temp-outputs/Makefile2
-rw-r--r--src/test/run-make/issue-7349/foo.rs2
-rw-r--r--src/test/run-make/save-analysis/foo.rs5
-rw-r--r--src/test/run-make/sepcomp-separate/foo.rs8
-rw-r--r--src/test/run-make/simd-ffi/simd.rs1
-rw-r--r--src/test/run-make/symbols-are-reasonable/lib.rs3
-rw-r--r--src/test/run-make/symbols-include-type-name/lib.rs5
-rw-r--r--src/test/run-make/target-specs/foo.rs1
-rw-r--r--src/test/run-pass/auto-is-contextual.rs24
-rw-r--r--src/test/run-pass/auto-traits.rs36
-rw-r--r--src/test/run-pass/closure-expected-type/README.md8
-rw-r--r--src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs26
-rw-r--r--src/test/run-pass/closure-expected-type/issue-38714.rs26
-rw-r--r--src/test/run-pass/closure-expected-type/supply-just-return-type.rs35
-rw-r--r--src/test/run-pass/closure-expected-type/supply-nothing.rs20
-rw-r--r--src/test/run-pass/issue-29516.rs1
-rw-r--r--src/test/run-pass/issue-45731.rs34
-rw-r--r--src/test/run-pass/mir-inlining/ice-issue-45493.rs26
-rw-r--r--src/test/run-pass/next-power-of-two-overflow-debug.rs36
-rw-r--r--src/test/run-pass/next-power-of-two-overflow-ndebug.rs24
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs19
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs23
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs18
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/enums.rs33
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs28
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/structs.rs27
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs40
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/variants.rs31
-rw-r--r--src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs34
-rw-r--r--src/test/run-pass/saturating-float-casts.rs164
-rw-r--r--src/test/rustdoc/auxiliary/rustdoc-default-impl.rs1
-rw-r--r--src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs1
-rw-r--r--src/test/rustdoc/impl-parts.rs1
-rw-r--r--src/test/rustdoc/issue-45584.rs25
-rw-r--r--src/test/rustdoc/method-list.rs30
-rw-r--r--src/test/rustdoc/playground-arg.rs2
-rw-r--r--src/test/rustdoc/playground.rs6
-rw-r--r--src/test/rustdoc/sidebar-items.rs59
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/test/ui/codemap_tests/unicode_2.rs17
-rw-r--r--src/test/ui/codemap_tests/unicode_2.stderr24
-rw-r--r--src/test/ui/codemap_tests/unicode_3.rs14
-rw-r--r--src/test/ui/codemap_tests/unicode_3.stderr10
-rw-r--r--src/test/ui/deref-suggestion.stderr4
-rw-r--r--src/test/ui/issue-35241.rs15
-rw-r--r--src/test/ui/issue-35241.stderr15
-rw-r--r--src/test/ui/issue-40782.rs15
-rw-r--r--src/test/ui/issue-40782.stderr8
-rw-r--r--src/test/ui/issue-44078.stderr2
-rw-r--r--src/test/ui/issue-44406.stderr11
-rw-r--r--src/test/ui/issue-45730.rs19
-rw-r--r--src/test/ui/issue-45730.stderr32
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs30
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr11
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs (renamed from src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs)0
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr11
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr11
-rw-r--r--src/test/ui/lint/unreachable_pub-pub_crate.rs74
-rw-r--r--src/test/ui/lint/unreachable_pub-pub_crate.stderr134
-rw-r--r--src/test/ui/lint/unreachable_pub.rs69
-rw-r--r--src/test/ui/lint/unreachable_pub.stderr134
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.rs2
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr92
-rw-r--r--src/test/ui/lint/use_suggestion_json.rs2
-rw-r--r--src/test/ui/lint/use_suggestion_json.stderr292
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr11
-rw-r--r--src/test/ui/nll/named-region-basic.rs22
-rw-r--r--src/test/ui/nll/named-region-basic.stderr29
-rw-r--r--src/test/ui/resolve/token-error-correct.stderr20
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/suggestion.rs15
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr10
-rw-r--r--src/test/ui/span/E0535.rs4
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-initializer.rs13
-rw-r--r--src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr17
m---------src/tools/cargo0
-rw-r--r--src/tools/cargotest/main.rs2
-rw-r--r--src/tools/compiletest/src/common.rs14
-rw-r--r--src/tools/compiletest/src/runtest.rs34
m---------src/tools/rls0
m---------src/tools/rustfmt24
452 files changed, 12948 insertions, 3605 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 69c3789f337..0263c74595f 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -491,11 +491,11 @@ dependencies = [
 
 [[package]]
 name = "derive-new"
-version = "0.3.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1349,11 +1349,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "quote"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
@@ -1452,7 +1447,7 @@ version = "0.1.0"
 
 [[package]]
 name = "rls"
-version = "0.122.0"
+version = "0.123.0"
 dependencies = [
  "cargo 0.24.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1461,12 +1456,12 @@ dependencies = [
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.13",
+ "rustfmt-nightly 0.2.14",
  "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1475,19 +1470,19 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-data"
-version = "0.11.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1839,6 +1834,7 @@ dependencies = [
  "arena 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -1849,7 +1845,7 @@ name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1873,6 +1869,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
+ "rustc_apfloat 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -1950,7 +1947,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.13"
+version = "0.2.14"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2189,15 +2186,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "syn"
-version = "0.8.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "syn"
 version = "0.11.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2244,6 +2232,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2639,7 +2628,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
-"checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e"
+"checksum derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "415f627ab054041c3eb748c2e1da0ef751989f5f0c386b63a098e545854a98ba"
 "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
 "checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
@@ -2726,7 +2715,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a656fdb8b6848f896df5e478a0eb9083681663e37dcb77dd16981ff65329fe8b"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
-"checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0"
 "checksum rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "61efcbcd9fa8d8fbb07c84e34a8af18a1ff177b449689ad38a6e9457ecc7b2ae"
@@ -2736,8 +2724,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd4e96e3a7d4cf3f31d789080ddd88fbe3251df2feb168049a24eda8b6046ed8"
-"checksum rls-data 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aea328fa69702c1b0fc395f2c71eae954bf984ac1e418c72f69221b6e3d15ff"
+"checksum rls-analysis 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10fbe17ed9da2fa3686ebb018958e194a4a25f0b3a78382bfe334d09d3c641f4"
+"checksum rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48257ceade23c2e01a3ca8d2fc4226101b107f6a3c868f829cf3fd2f204a1fe6"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
@@ -2767,7 +2755,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
-"checksum syn 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ae6fb0dcc9bd85f89a1a4adc0df2fd90c90c98849d61433983dd7a9df6363f7"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e52bffe6202cfb67587784cf23e0ec5bf26d331eef4922a16d5c42e12aa1e9b"
 "checksum syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "955ef4b16af4c468e4680d1497f873ff288f557d338180649e18f915af5e15ac"
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 608924c9c28..c150459bee5 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -27,10 +27,8 @@ pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
     install_sh(builder, "docs", "rust-docs", stage, Some(host));
 }
 
-pub fn install_std(builder: &Builder, stage: u32) {
-    for target in &builder.build.targets {
-        install_sh(builder, "std", "rust-std", stage, Some(*target));
-    }
+pub fn install_std(builder: &Builder, stage: u32, target: Interned<String>) {
+    install_sh(builder, "std", "rust-std", stage, Some(target));
 }
 
 pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
@@ -175,19 +173,24 @@ install!((self, builder, _config),
         install_docs(builder, self.stage, self.target);
     };
     Std, "src/libstd", true, only_hosts: true, {
-        builder.ensure(dist::Std {
-            compiler: builder.compiler(self.stage, self.host),
-            target: self.target
-        });
-        install_std(builder, self.stage);
+        for target in &builder.build.targets {
+            builder.ensure(dist::Std {
+                compiler: builder.compiler(self.stage, self.host),
+                target: *target
+            });
+            install_std(builder, self.stage, *target);
+        }
     };
     Cargo, "cargo", _config.extended, only_hosts: true, {
         builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
         install_cargo(builder, self.stage, self.target);
     };
     Rls, "rls", _config.extended, only_hosts: true, {
-        builder.ensure(dist::Rls { stage: self.stage, target: self.target });
-        install_rls(builder, self.stage, self.target);
+        if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() {
+            install_rls(builder, self.stage, self.target);
+        } else {
+            println!("skipping Install RLS stage{} ({})", self.stage, self.target);
+        }
     };
     Analysis, "analysis", _config.extended, only_hosts: false, {
         builder.ensure(dist::Analysis {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 19409ef779e..fce6755aea9 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -323,9 +323,9 @@ impl Step for TestHelpers {
     }
 }
 
-const OPENSSL_VERS: &'static str = "1.0.2k";
+const OPENSSL_VERS: &'static str = "1.0.2m";
 const OPENSSL_SHA256: &'static str =
-    "6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0";
+    "8c6ff15ec6b319b50788f42c7abc2890c08ba5a1cdcd3810eb9092deada37b0f";
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Openssl {
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 688ee6ba295..7175fed5410 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -415,7 +415,8 @@ impl Step for Clippy {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.path("src/tools/clippy")
+        let builder = run.builder;
+        run.path("src/tools/clippy").default_condition(builder.build.config.extended)
     }
 
     fn make_run(run: RunConfig) {
diff --git a/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh b/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
index 4d3e638916d..f231d20b197 100755
--- a/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
+++ b/src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
@@ -23,9 +23,9 @@ SYSROOT=/usr/local/$TARGET/sysroot
 mkdir -p $SYSROOT
 pushd $SYSROOT
 
-centos_base=http://mirror.centos.org/altarch/7.3.1611/os/ppc64le/Packages
-glibc_v=2.17-157.el7
-kernel_v=3.10.0-514.el7
+centos_base=http://mirror.centos.org/altarch/7/os/ppc64le/Packages
+glibc_v=2.17-196.el7
+kernel_v=3.10.0-693.el7
 for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
   curl $centos_base/$package.ppc64le.rpm | \
     rpm2cpio - | cpio -idm
diff --git a/src/doc/not_found.md b/src/doc/not_found.md
index 5d632ebc68f..ebe7c59313f 100644
--- a/src/doc/not_found.md
+++ b/src/doc/not_found.md
@@ -22,7 +22,7 @@ Some things that might be helpful to you though:
 # Reference
 
 * [The Rust official site](https://www.rust-lang.org)
-* [The Rust reference](https://doc.rust-lang.org/reference.html)
+* [The Rust reference](https://doc.rust-lang.org/reference/index.html)
 
 # Docs
 
diff --git a/src/doc/unstable-book/src/language-features/non-exhaustive.md b/src/doc/unstable-book/src/language-features/non-exhaustive.md
new file mode 100644
index 00000000000..f9840e1b83f
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/non-exhaustive.md
@@ -0,0 +1,75 @@
+# `non_exhaustive`
+
+The tracking issue for this feature is: [#44109]
+
+[#44109]: https://github.com/rust-lang/rust/issues/44109
+
+------------------------
+
+The `non_exhaustive` gate allows you to use the `#[non_exhaustive]` attribute
+on structs and enums. When applied within a crate, users of the crate will need
+to use the `_` pattern when matching enums and use the `..` pattern when
+matching structs. Structs marked as `non_exhaustive` will not be able to be
+created normally outside of the defining crate. This is demonstrated below:
+
+```rust,ignore (pseudo-Rust)
+use std::error::Error as StdError;
+
+#[non_exhaustive]
+pub enum Error {
+    Message(String),
+    Other,
+}
+impl StdError for Error {
+    fn description(&self) -> &str {
+        // This will not error, despite being marked as non_exhaustive, as this
+        // enum is defined within the current crate, it can be matched
+        // exhaustively.
+        match *self {
+            Message(ref s) => s,
+            Other => "other or unknown error",
+        }
+    }
+}
+```
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Error;
+
+// This will not error as the non_exhaustive Error enum has been matched with
+// a wildcard.
+match error {
+    Message(ref s) => ...,
+    Other => ...,
+    _ => ...,
+}
+```
+
+```rust,ignore (pseudo-Rust)
+#[non_exhaustive]
+pub struct Config {
+    pub window_width: u16,
+    pub window_height: u16,
+}
+
+// We can create structs as normal within the defining crate when marked as
+// non_exhaustive.
+let config = Config { window_width: 640, window_height: 480 };
+
+// We can match structs exhaustively when within the defining crate.
+if let Ok(Config { window_width, window_height }) = load_config() {
+    // ...
+}
+```
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Config;
+
+// We cannot create a struct like normal if it has been marked as
+// non_exhaustive.
+let config = Config { window_width: 640, window_height: 480 };
+// By adding the `..` we can match the config as below outside of the crate
+// when marked non_exhaustive.
+let &Config { window_width, window_height, .. } = config;
+```
+
diff --git a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md
index ee24dd87d90..97b57c690fc 100644
--- a/src/doc/unstable-book/src/language-features/optin-builtin-traits.md
+++ b/src/doc/unstable-book/src/language-features/optin-builtin-traits.md
@@ -24,9 +24,7 @@ Example:
 ```rust
 #![feature(optin_builtin_traits)]
 
-trait Valid {}
-
-impl Valid for .. {}
+auto trait Valid {}
 
 struct True;
 struct False;
diff --git a/src/etc/char_private.py b/src/etc/char_private.py
index 75ab3f1a17b..cfe5b01e934 100644
--- a/src/etc/char_private.py
+++ b/src/etc/char_private.py
@@ -177,7 +177,7 @@ def main():
     normal1 = compress_normal(normal1)
 
     print("""\
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -226,7 +226,7 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
     current
 }
 
-pub fn is_printable(x: char) -> bool {
+pub(crate) fn is_printable(x: char) -> bool {
     let x = x as u32;
     let lower = x as u16;
     if x < 0x10000 {
diff --git a/src/liballoc/benches/str.rs b/src/liballoc/benches/str.rs
index fc4063fae92..38c94d4d8b5 100644
--- a/src/liballoc/benches/str.rs
+++ b/src/liballoc/benches/str.rs
@@ -272,15 +272,12 @@ make_test!(match_indices_a_str, s, s.match_indices("a").count());
 make_test!(split_a_str, s, s.split("a").count());
 
 make_test!(trim_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_matches(|c: char| c.is_ascii())
 });
 make_test!(trim_left_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_left_matches(|c: char| c.is_ascii())
 });
 make_test!(trim_right_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_right_matches(|c: char| c.is_ascii())
 });
 
diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs
index a662e4b1f4f..e8aff099871 100644
--- a/src/liballoc/borrow.rs
+++ b/src/liballoc/borrow.rs
@@ -191,7 +191,6 @@ impl<'a, B: ?Sized> Cow<'a, B>
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
     /// use std::borrow::Cow;
     ///
     /// let mut cow = Cow::Borrowed("foo");
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 0cbfc9e9dac..a40ed060604 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -83,6 +83,7 @@
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(rand, test))]
 #![feature(allow_internal_unstable)]
+#![feature(ascii_ctype)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
@@ -93,6 +94,7 @@
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(fmt_internals)]
+#![feature(from_ref)]
 #![feature(fundamental)]
 #![feature(fused)]
 #![feature(generic_param_attrs)]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 841f9dc6414..dbf1fb1367d 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -114,7 +114,7 @@ impl<T, A: Alloc> RawVec<T, A> {
 impl<T> RawVec<T, Heap> {
     /// Creates the biggest possible RawVec (on the system heap)
     /// without allocating. If T has positive size, then this makes a
-    /// RawVec with capacity 0. If T has 0 size, then it it makes a
+    /// RawVec with capacity 0. If T has 0 size, then it makes a
     /// RawVec with capacity `usize::MAX`. Useful for implementing
     /// delayed allocation.
     pub fn new() -> Self {
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 2045d5ddd97..b41cb912fe7 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -119,6 +119,8 @@ pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{RSplit, RSplitMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
+#[unstable(feature = "from_ref", issue = "45703")]
+pub use core::slice::{from_ref, from_ref_mut};
 #[unstable(feature = "slice_get_slice", issue = "35729")]
 pub use core::slice::SliceIndex;
 
@@ -1531,6 +1533,215 @@ impl<T> [T] {
     }
 }
 
+// FIXME(LukasKalbertodt): the `not(stage0)` constraint can be removed in the
+// future once the stage0 compiler is new enough to know about the `slice_u8`
+// lang item.
+#[lang = "slice_u8"]
+#[cfg(all(not(stage0), not(test)))]
+impl [u8] {
+    /// Checks if all bytes in this slice are within the ASCII range.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        self.iter().all(|b| b.is_ascii())
+    }
+
+    /// Returns a vector containing a copy of this slice where each byte
+    /// is mapped to its ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> Vec<u8> {
+        let mut me = self.to_vec();
+        me.make_ascii_uppercase();
+        me
+    }
+
+    /// Returns a vector containing a copy of this slice where each byte
+    /// is mapped to its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> Vec<u8> {
+        let mut me = self.to_vec();
+        me.make_ascii_lowercase();
+        me
+    }
+
+    /// Checks that two slices are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+        self.len() == other.len() &&
+            self.iter().zip(other).all(|(a, b)| {
+                a.eq_ignore_ascii_case(b)
+            })
+    }
+
+    /// Converts this slice to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_uppercase();
+        }
+    }
+
+    /// Converts this slice to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_lowercase();
+        }
+    }
+
+    /// Checks if all bytes of this slice are ASCII alphabetic characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_alphabetic())
+    }
+
+    /// Checks if all bytes of this slice are ASCII uppercase characters:
+    /// U+0041 'A' ... U+005A 'Z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_uppercase())
+    }
+
+    /// Checks if all bytes of this slice are ASCII lowercase characters:
+    /// U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_lowercase())
+    }
+
+    /// Checks if all bytes of this slice are ASCII alphanumeric characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_alphanumeric())
+    }
+
+    /// Checks if all bytes of this slice are ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_digit())
+    }
+
+    /// Checks if all bytes of this slice are ASCII hexadecimal digits:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_hexdigit())
+    }
+
+    /// Checks if all bytes of this slice are ASCII punctuation characters:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_punctuation())
+    }
+
+    /// Checks if all bytes of this slice are ASCII graphic characters:
+    /// U+0021 '@' ... U+007E '~'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_graphic())
+    }
+
+    /// Checks if all bytes of this slice are ASCII whitespace characters:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_whitespace())
+    }
+
+    /// Checks if all bytes of this slice are ASCII control characters:
+    ///
+    /// - U+0000 NUL ... U+001F UNIT SEPARATOR, or
+    /// - U+007F DELETE.
+    ///
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_control())
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 895607ff8d4..5f0b4088fc0 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -390,8 +390,6 @@ impl str {
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut v = String::from("hello");
     /// // correct length
     /// assert!(v.get_mut(0..5).is_some());
@@ -617,8 +615,6 @@ impl str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut s = "Per Martin-Löf".to_string();
     /// {
     ///     let (first, last) = s.split_at_mut(3);
@@ -2070,6 +2066,286 @@ impl str {
         s.extend((0..n).map(|_| self));
         s
     }
+
+    /// Checks if all characters in this string are within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = "hello!\n";
+    /// let non_ascii = "Grüße, Jürgen ❤";
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        // We can treat each byte as character here: all multibyte characters
+        // start with a byte that is not in the ascii range, so we will stop
+        // there already.
+        self.bytes().all(|b| b.is_ascii())
+    }
+
+    /// Returns a copy of this string where each character is mapped to its
+    /// ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// To uppercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Grüße, Jürgen ❤";
+    ///
+    /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`to_uppercase`]: #method.to_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn to_ascii_uppercase(&self) -> String {
+        let mut bytes = self.as_bytes().to_vec();
+        bytes.make_ascii_uppercase();
+        // make_ascii_uppercase() preserves the UTF-8 invariant.
+        unsafe { String::from_utf8_unchecked(bytes) }
+    }
+
+    /// Returns a copy of this string where each character is mapped to its
+    /// ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// To lowercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Grüße, Jürgen ❤";
+    ///
+    /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`to_lowercase`]: #method.to_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn to_ascii_lowercase(&self) -> String {
+        let mut bytes = self.as_bytes().to_vec();
+        bytes.make_ascii_lowercase();
+        // make_ascii_lowercase() preserves the UTF-8 invariant.
+        unsafe { String::from_utf8_unchecked(bytes) }
+    }
+
+    /// Checks that two strings are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
+    /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
+    /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
+        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
+    }
+
+    /// Converts this string to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[cfg(not(stage0))]
+    pub fn make_ascii_uppercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_uppercase()
+    }
+
+    /// Converts this string to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[cfg(not(stage0))]
+    pub fn make_ascii_lowercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_lowercase()
+    }
+
+    /// Checks if all characters of this string are ASCII alphabetic
+    /// characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_alphabetic())
+    }
+
+    /// Checks if all characters of this string are ASCII uppercase characters:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// // Only ascii uppercase characters
+    /// assert!("HELLO".is_ascii_uppercase());
+    ///
+    /// // While all characters are ascii, 'y' and 'e' are not uppercase
+    /// assert!(!"Bye".is_ascii_uppercase());
+    ///
+    /// // While all characters are uppercase, 'Ü' is not ascii
+    /// assert!(!"TSCHÜSS".is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_uppercase())
+    }
+
+    /// Checks if all characters of this string are ASCII lowercase characters:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// // Only ascii uppercase characters
+    /// assert!("hello".is_ascii_lowercase());
+    ///
+    /// // While all characters are ascii, 'B' is not lowercase
+    /// assert!(!"Bye".is_ascii_lowercase());
+    ///
+    /// // While all characters are lowercase, 'Ü' is not ascii
+    /// assert!(!"tschüss".is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_lowercase())
+    }
+
+    /// Checks if all characters of this string are ASCII alphanumeric
+    /// characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_alphanumeric())
+    }
+
+    /// Checks if all characters of this string are ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_digit())
+    }
+
+    /// Checks if all characters of this string are ASCII hexadecimal digits:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_hexdigit())
+    }
+
+    /// Checks if all characters of this string are ASCII punctuation
+    /// characters:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_punctuation())
+    }
+
+    /// Checks if all characters of this string are ASCII graphic characters:
+    /// U+0021 '@' ... U+007E '~'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_graphic())
+    }
+
+    /// Checks if all characters of this string are ASCII whitespace characters:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_whitespace())
+    }
+
+    /// Checks if all characters of this string are ASCII control characters:
+    ///
+    /// - U+0000 NUL ... U+001F UNIT SEPARATOR, or
+    /// - U+007F DELETE.
+    ///
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_control())
+    }
 }
 
 /// Converts a boxed slice of bytes to a boxed string slice without checking
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 6d0bb264df1..25fcc1ccdab 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -773,8 +773,6 @@ impl String {
     /// Basic usage:
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut s = String::from("foobar");
     /// let s_mut_str = s.as_mut_str();
     ///
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index b3178064505..6b075e7ac0e 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -706,7 +706,6 @@ fn test_split_at() {
 
 #[test]
 fn test_split_at_mut() {
-    use std::ascii::AsciiExt;
     let mut s = "Hello World".to_string();
     {
         let (a, b) = s.split_at_mut(5);
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 0e25da5bd30..9cfde5dcc73 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::mem::size_of;
 use std::panic;
@@ -966,5 +965,3 @@ fn drain_filter_complex() {
         assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
     }
 }
-
-
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index cf34e195dea..5aca199cf40 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -853,8 +853,6 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
     ///
     /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index d153f19c462..f060f6d79c1 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -107,7 +107,7 @@ mod contents {
     // ABI
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc(size: usize,
                                      align: usize,
                                      err: *mut u8) -> *mut u8 {
@@ -122,13 +122,13 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
         System.oom((*(err as *const AllocErr)).clone())
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -137,7 +137,7 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                            min: *mut usize,
                                            max: *mut usize) {
@@ -153,7 +153,7 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                        _old_size: usize,
                                        old_align: usize,
@@ -177,7 +177,7 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                             align: usize,
                                             err: *mut u8) -> *mut u8 {
@@ -196,20 +196,21 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc_excess(size: usize,
                                             align: usize,
                                             excess: *mut usize,
                                             err: *mut u8) -> *mut u8 {
         let p = __rde_alloc(size, align, err);
         if !p.is_null() {
-            *excess = size;
+            let flags = align_to_flags(align);
+            *excess = nallocx(size, flags) as usize;
         }
         return p
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                               old_size: usize,
                                               old_align: usize,
@@ -219,13 +220,14 @@ mod contents {
                                               err: *mut u8) -> *mut u8 {
         let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
         if !p.is_null() {
-            *excess = new_size;
+            let flags = align_to_flags(new_align);
+            *excess = nallocx(new_size, flags) as usize;
         }
-        return p
+        p
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
@@ -235,7 +237,7 @@ mod contents {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                                _old_size: usize,
                                                old_align: usize,
diff --git a/src/libbacktrace/configure b/src/libbacktrace/configure
index df6497fc646..873220794bd 100755
--- a/src/libbacktrace/configure
+++ b/src/libbacktrace/configure
@@ -12323,6 +12323,12 @@ fi
 
   fi
 fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
 if test "$have_mmap" = "no"; then
   VIEW_FILE=read.lo
   ALLOC_FILE=alloc.lo
diff --git a/src/libbacktrace/configure.ac b/src/libbacktrace/configure.ac
index 7ae21b8d1a6..ea1b27d807e 100644
--- a/src/libbacktrace/configure.ac
+++ b/src/libbacktrace/configure.ac
@@ -283,6 +283,12 @@ else
     AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
   fi
 fi
+
+case "${host_os}" in
+darwin*)
+  have_mmap=no ;;
+esac
+
 if test "$have_mmap" = "no"; then
   VIEW_FILE=read.lo
   ALLOC_FILE=alloc.lo
diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs
index 2c0f449b276..e6803745ab5 100644
--- a/src/libcore/char_private.rs
+++ b/src/libcore/char_private.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -47,7 +47,7 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8],
     current
 }
 
-pub fn is_printable(x: char) -> bool {
+pub(crate) fn is_printable(x: char) -> bool {
     let x = x as u32;
     let lower = x as u16;
     if x < 0x10000 {
@@ -64,7 +64,10 @@ pub fn is_printable(x: char) -> bool {
         if 0x2b81e <= x && x < 0x2b820 {
             return false;
         }
-        if 0x2cea2 <= x && x < 0x2f800 {
+        if 0x2cea2 <= x && x < 0x2ceb0 {
+            return false;
+        }
+        if 0x2ebe1 <= x && x < 0x2f800 {
             return false;
         }
         if 0x2fa1e <= x && x < 0xe0100 {
@@ -83,12 +86,12 @@ const SINGLETONS0U: &'static [(u8, u8)] = &[
     (0x05, 8),
     (0x06, 3),
     (0x07, 4),
-    (0x08, 7),
+    (0x08, 8),
     (0x09, 16),
     (0x0a, 27),
-    (0x0b, 24),
+    (0x0b, 25),
     (0x0c, 22),
-    (0x0d, 20),
+    (0x0d, 18),
     (0x0e, 22),
     (0x0f, 4),
     (0x10, 3),
@@ -99,16 +102,15 @@ const SINGLETONS0U: &'static [(u8, u8)] = &[
     (0x18, 2),
     (0x19, 3),
     (0x1a, 7),
-    (0x1c, 1),
+    (0x1d, 1),
     (0x1f, 22),
     (0x20, 3),
-    (0x23, 1),
     (0x2b, 5),
     (0x2c, 2),
     (0x2d, 11),
     (0x2e, 1),
     (0x30, 3),
-    (0x31, 1),
+    (0x31, 3),
     (0x32, 2),
     (0xa7, 1),
     (0xa8, 2),
@@ -125,19 +127,19 @@ const SINGLETONS0L: &'static [u8] = &[
     0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57,
     0x58, 0x60, 0x88, 0x8b, 0x8c, 0x90, 0x1c, 0x1d,
     0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0x2e, 0x2f, 0x3f,
-    0x5c, 0x5d, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91,
-    0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9,
-    0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12, 0x29,
-    0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a,
-    0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba,
-    0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, 0x04,
-    0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a,
-    0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65,
-    0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, 0xcf, 0x04,
-    0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65,
-    0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5,
-    0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04, 0x0d, 0x11,
-    0x3b, 0x3c, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
+    0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e,
+    0x91, 0x92, 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6,
+    0xc9, 0xca, 0xde, 0xe4, 0xe5, 0x04, 0x11, 0x12,
+    0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49,
+    0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4,
+    0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5,
+    0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31,
+    0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e,
+    0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce,
+    0xcf, 0x04, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57,
+    0x64, 0x65, 0x84, 0x8d, 0x91, 0xa9, 0xb4, 0xba,
+    0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x04,
+    0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x81,
     0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, 0xf0,
     0xf1, 0x83, 0x85, 0x86, 0x89, 0x8b, 0x8c, 0x98,
     0xa0, 0xa4, 0xa6, 0xa8, 0xa9, 0xac, 0xba, 0xbe,
@@ -148,18 +150,18 @@ const SINGLETONS0L: &'static [u8] = &[
     0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe,
     0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e,
     0x0f, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d,
-    0x7e, 0xae, 0xaf, 0xf7, 0x16, 0x17, 0x1e, 0x1f,
+    0x7e, 0xae, 0xaf, 0xfa, 0x16, 0x17, 0x1e, 0x1f,
     0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e,
     0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0,
-    0xf1, 0xf5, 0x72, 0x73, 0x8f, 0xff, 0x74, 0x75,
-    0x96, 0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f,
-    0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf,
-    0x9a, 0x40, 0x97, 0x98, 0x8f, 0x1f, 0xff, 0xaf,
-    0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b,
-    0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, 0xef,
-    0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90,
-    0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9,
-    0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
+    0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96,
+    0x97, 0xc9, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7,
+    0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a,
+    0x40, 0x97, 0x98, 0x2f, 0x30, 0x8f, 0x1f, 0xff,
+    0xaf, 0xfe, 0xff, 0xce, 0xff, 0x4e, 0x4f, 0x5a,
+    0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee,
+    0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45,
+    0x90, 0x91, 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8,
+    0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
 ];
 const SINGLETONS1U: &'static [(u8, u8)] = &[
     (0x00, 6),
@@ -176,7 +178,9 @@ const SINGLETONS1U: &'static [(u8, u8)] = &[
     (0x13, 18),
     (0x14, 2),
     (0x15, 2),
+    (0x1a, 3),
     (0x1c, 5),
+    (0x1d, 4),
     (0x24, 1),
     (0x6a, 3),
     (0x6b, 2),
@@ -192,7 +196,7 @@ const SINGLETONS1U: &'static [(u8, u8)] = &[
     (0xee, 32),
     (0xf0, 4),
     (0xf1, 1),
-    (0xf9, 4),
+    (0xf9, 1),
 ];
 const SINGLETONS1L: &'static [u8] = &[
     0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e,
@@ -202,18 +206,18 @@ const SINGLETONS1L: &'static [u8] = &[
     0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12,
     0x29, 0x31, 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49,
     0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5a, 0x5c, 0xb6,
-    0xb7, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x6f, 0x5f,
-    0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28,
-    0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8,
-    0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15,
-    0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc,
-    0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5,
-    0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33,
-    0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55,
-    0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65,
-    0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4,
-    0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x1f, 0x31,
-    0x32, 0x3f,
+    0xb7, 0x84, 0x85, 0x9d, 0x09, 0x37, 0x90, 0x91,
+    0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x6f, 0x5f, 0xee,
+    0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, 0x28, 0x55,
+    0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad,
+    0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d,
+    0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd,
+    0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0xc5, 0xc6,
+    0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38,
+    0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56,
+    0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66,
+    0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa,
+    0xaf, 0xb0, 0xc0, 0xd0, 0x2f, 0x3f,
 ];
 const NORMAL0: &'static [u8] = &[
     0x00, 0x20,
@@ -224,12 +228,12 @@ const NORMAL0: &'static [u8] = &[
     0x05, 0x11,
     0x81, 0xac, 0x0e,
     0x3b, 0x05,
-    0x5f, 0x41,
+    0x6b, 0x35,
     0x1e, 0x16,
     0x80, 0xdf, 0x03,
     0x19, 0x08,
     0x01, 0x04,
-    0x20, 0x05,
+    0x22, 0x03,
     0x0a, 0x04,
     0x34, 0x04,
     0x07, 0x03,
@@ -238,8 +242,7 @@ const NORMAL0: &'static [u8] = &[
     0x10, 0x0b,
     0x50, 0x0f,
     0x12, 0x07,
-    0x01, 0x07,
-    0x4d, 0x08,
+    0x55, 0x08,
     0x02, 0x04,
     0x1c, 0x0a,
     0x09, 0x03,
@@ -258,8 +261,8 @@ const NORMAL0: &'static [u8] = &[
     0x10, 0x08,
     0x56, 0x07,
     0x02, 0x07,
-    0x15, 0x0e,
-    0x4f, 0x04,
+    0x15, 0x0d,
+    0x50, 0x04,
     0x43, 0x03,
     0x2d, 0x03,
     0x01, 0x04,
@@ -304,34 +307,32 @@ const NORMAL0: &'static [u8] = &[
     0x3c, 0x37,
     0x08, 0x08,
     0x2a, 0x06,
-    0x80, 0xf6, 0x05,
-    0x82, 0x04, 0x11,
+    0x82, 0xff, 0x11,
     0x18, 0x08,
     0x2f, 0x11,
     0x2d, 0x03,
-    0x1f, 0x11,
+    0x20, 0x10,
     0x21, 0x0f,
     0x80, 0x8c, 0x04,
     0x82, 0x97, 0x19,
     0x0b, 0x15,
     0x87, 0x5a, 0x03,
-    0x15, 0x1a,
+    0x16, 0x19,
     0x04, 0x10,
     0x80, 0xf4, 0x05,
     0x2f, 0x05,
     0x3b, 0x07,
     0x02, 0x0e,
     0x18, 0x09,
-    0x80, 0xa5, 0x3b,
+    0x80, 0xaa, 0x36,
     0x74, 0x0c,
     0x80, 0xd6, 0x1a,
     0x0c, 0x05,
     0x80, 0xff, 0x05,
-    0x29, 0x03,
-    0x80, 0x8a, 0x05,
+    0x80, 0xb6, 0x05,
     0x24, 0x0c,
     0x9b, 0xc6, 0x0a,
-    0xd2, 0x16, 0x2a,
+    0xd2, 0x2b, 0x15,
     0x84, 0x8d, 0x03,
     0x37, 0x09,
     0x81, 0x5c, 0x14,
@@ -378,8 +379,8 @@ const NORMAL1: &'static [u8] = &[
     0x1d, 0x03,
     0x31, 0x0f,
     0x1c, 0x04,
-    0x24, 0x0c,
-    0x1b, 0x05,
+    0x24, 0x09,
+    0x1e, 0x05,
     0x2b, 0x05,
     0x44, 0x04,
     0x0e, 0x2a,
@@ -447,11 +448,16 @@ const NORMAL1: &'static [u8] = &[
     0x0f, 0x04,
     0x10, 0x81, 0x60,
     0x53, 0x0c,
-    0x01, 0x81, 0xc0,
+    0x01, 0x81, 0x00,
+    0x48, 0x08,
+    0x53, 0x1d,
     0x39, 0x81, 0x07,
     0x46, 0x0a,
     0x1d, 0x03,
-    0x47, 0x83, 0x49,
+    0x47, 0x49,
+    0x37, 0x03,
+    0x0e, 0x08,
+    0x0a, 0x82, 0xa6,
     0x83, 0x9a, 0x66,
     0x75, 0x0b,
     0x80, 0xc4, 0x8a, 0xbc,
@@ -467,10 +473,11 @@ const NORMAL1: &'static [u8] = &[
     0x45, 0x0b,
     0x2f, 0x10,
     0x11, 0x40,
-    0x01, 0x1f,
+    0x02, 0x1e,
     0x97, 0xed, 0x13,
     0x82, 0xf3, 0xa5, 0x0d,
-    0x02, 0x8b, 0xfe,
+    0x81, 0x1f, 0x51,
+    0x81, 0x8c, 0x89, 0x04,
     0x6b, 0x05,
     0x0d, 0x03,
     0x09, 0x07,
@@ -503,20 +510,22 @@ const NORMAL1: &'static [u8] = &[
     0x1d, 0x0d,
     0x2c, 0x04,
     0x09, 0x07,
-    0x02, 0x80, 0xae,
-    0x83, 0xd3, 0x0d,
+    0x02, 0x0e,
+    0x06, 0x80, 0x9a,
+    0x83, 0xd5, 0x0b,
     0x0d, 0x03,
-    0x07, 0x09,
+    0x09, 0x07,
     0x74, 0x0c,
     0x55, 0x2b,
     0x0c, 0x04,
     0x38, 0x08,
     0x0a, 0x06,
     0x28, 0x08,
-    0x1e, 0x62,
-    0x18, 0x08,
-    0x1c, 0x04,
-    0x0f, 0x21,
-    0x12, 0x2e,
-    0x01, 0x86, 0x3f,
+    0x1e, 0x52,
+    0x0c, 0x04,
+    0x3d, 0x03,
+    0x1c, 0x14,
+    0x18, 0x28,
+    0x01, 0x0f,
+    0x17, 0x86, 0x19,
 ];
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 5659d5b8d66..4a57417e86a 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -189,3 +189,4 @@ pub mod fmt;
 mod char_private;
 mod iter_private;
 mod tuple;
+mod unit;
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index f56a9a40332..e47b99ed552 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -46,6 +46,8 @@ pub unsafe trait Send {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Send for .. { }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -349,6 +351,8 @@ pub unsafe trait Sync {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Sync for .. { }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -562,6 +566,8 @@ mod impls {
 #[lang = "freeze"]
 unsafe trait Freeze {}
 
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Freeze for .. {}
 
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 5799d37c19c..7fe0aabeec9 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -15,6 +15,7 @@
 use convert::{Infallible, TryFrom};
 use fmt;
 use intrinsics;
+use ops;
 use str::FromStr;
 
 /// Provides intentionally-wrapped arithmetic on `T`.
@@ -2223,7 +2224,8 @@ macro_rules! uint_impl {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn next_power_of_two(self) -> Self {
-            self.one_less_than_next_power_of_two() + 1
+            // Call the trait to get overflow checks
+            ops::Add::add(self.one_less_than_next_power_of_two(), 1)
         }
 
         /// Returns the smallest power of two greater than or equal to `n`. If
@@ -2257,6 +2259,547 @@ impl u8 {
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
+
+
+    /// Checks if the value is within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 97u8;
+    /// let non_ascii = 150u8;
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        *self & 128 == 0
+    }
+
+    /// Makes a copy of the value in its ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let lowercase_a = 97u8;
+    ///
+    /// assert_eq!(65, lowercase_a.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> u8 {
+        ASCII_UPPERCASE_MAP[*self as usize]
+    }
+
+    /// Makes a copy of the value in its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let uppercase_a = 65u8;
+    ///
+    /// assert_eq!(97, uppercase_a.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> u8 {
+        ASCII_LOWERCASE_MAP[*self as usize]
+    }
+
+    /// Checks that two values are an ASCII case-insensitive match.
+    ///
+    /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let lowercase_a = 97u8;
+    /// let uppercase_a = 65u8;
+    ///
+    /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
+        self.to_ascii_lowercase() == other.to_ascii_lowercase()
+    }
+
+    /// Converts this value to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut byte = b'a';
+    ///
+    /// byte.make_ascii_uppercase();
+    ///
+    /// assert_eq!(b'A', byte);
+    /// ```
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        *self = self.to_ascii_uppercase();
+    }
+
+    /// Converts this value to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut byte = b'A';
+    ///
+    /// byte.make_ascii_lowercase();
+    ///
+    /// assert_eq!(b'a', byte);
+    /// ```
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        *self = self.to_ascii_lowercase();
+    }
+
+    /// Checks if the value is an ASCII alphabetic character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_alphabetic());
+    /// assert!(uppercase_g.is_ascii_alphabetic());
+    /// assert!(a.is_ascii_alphabetic());
+    /// assert!(g.is_ascii_alphabetic());
+    /// assert!(!zero.is_ascii_alphabetic());
+    /// assert!(!percent.is_ascii_alphabetic());
+    /// assert!(!space.is_ascii_alphabetic());
+    /// assert!(!lf.is_ascii_alphabetic());
+    /// assert!(!esc.is_ascii_alphabetic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            L | Lx | U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII uppercase character:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_uppercase());
+    /// assert!(uppercase_g.is_ascii_uppercase());
+    /// assert!(!a.is_ascii_uppercase());
+    /// assert!(!g.is_ascii_uppercase());
+    /// assert!(!zero.is_ascii_uppercase());
+    /// assert!(!percent.is_ascii_uppercase());
+    /// assert!(!space.is_ascii_uppercase());
+    /// assert!(!lf.is_ascii_uppercase());
+    /// assert!(!esc.is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII lowercase character:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_lowercase());
+    /// assert!(!uppercase_g.is_ascii_lowercase());
+    /// assert!(a.is_ascii_lowercase());
+    /// assert!(g.is_ascii_lowercase());
+    /// assert!(!zero.is_ascii_lowercase());
+    /// assert!(!percent.is_ascii_lowercase());
+    /// assert!(!space.is_ascii_lowercase());
+    /// assert!(!lf.is_ascii_lowercase());
+    /// assert!(!esc.is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            L | Lx => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII alphanumeric character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_alphanumeric());
+    /// assert!(uppercase_g.is_ascii_alphanumeric());
+    /// assert!(a.is_ascii_alphanumeric());
+    /// assert!(g.is_ascii_alphanumeric());
+    /// assert!(zero.is_ascii_alphanumeric());
+    /// assert!(!percent.is_ascii_alphanumeric());
+    /// assert!(!space.is_ascii_alphanumeric());
+    /// assert!(!lf.is_ascii_alphanumeric());
+    /// assert!(!esc.is_ascii_alphanumeric());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D | L | Lx | U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_digit());
+    /// assert!(!uppercase_g.is_ascii_digit());
+    /// assert!(!a.is_ascii_digit());
+    /// assert!(!g.is_ascii_digit());
+    /// assert!(zero.is_ascii_digit());
+    /// assert!(!percent.is_ascii_digit());
+    /// assert!(!space.is_ascii_digit());
+    /// assert!(!lf.is_ascii_digit());
+    /// assert!(!esc.is_ascii_digit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII hexadecimal digit:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_hexdigit());
+    /// assert!(!uppercase_g.is_ascii_hexdigit());
+    /// assert!(a.is_ascii_hexdigit());
+    /// assert!(!g.is_ascii_hexdigit());
+    /// assert!(zero.is_ascii_hexdigit());
+    /// assert!(!percent.is_ascii_hexdigit());
+    /// assert!(!space.is_ascii_hexdigit());
+    /// assert!(!lf.is_ascii_hexdigit());
+    /// assert!(!esc.is_ascii_hexdigit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D | Lx | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII punctuation character:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_punctuation());
+    /// assert!(!uppercase_g.is_ascii_punctuation());
+    /// assert!(!a.is_ascii_punctuation());
+    /// assert!(!g.is_ascii_punctuation());
+    /// assert!(!zero.is_ascii_punctuation());
+    /// assert!(percent.is_ascii_punctuation());
+    /// assert!(!space.is_ascii_punctuation());
+    /// assert!(!lf.is_ascii_punctuation());
+    /// assert!(!esc.is_ascii_punctuation());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            P => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII graphic character:
+    /// U+0021 '@' ... U+007E '~'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_graphic());
+    /// assert!(uppercase_g.is_ascii_graphic());
+    /// assert!(a.is_ascii_graphic());
+    /// assert!(g.is_ascii_graphic());
+    /// assert!(zero.is_ascii_graphic());
+    /// assert!(percent.is_ascii_graphic());
+    /// assert!(!space.is_ascii_graphic());
+    /// assert!(!lf.is_ascii_graphic());
+    /// assert!(!esc.is_ascii_graphic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            Ux | U | Lx | L | D | P => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII whitespace character:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_whitespace());
+    /// assert!(!uppercase_g.is_ascii_whitespace());
+    /// assert!(!a.is_ascii_whitespace());
+    /// assert!(!g.is_ascii_whitespace());
+    /// assert!(!zero.is_ascii_whitespace());
+    /// assert!(!percent.is_ascii_whitespace());
+    /// assert!(space.is_ascii_whitespace());
+    /// assert!(lf.is_ascii_whitespace());
+    /// assert!(!esc.is_ascii_whitespace());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            Cw | W => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII control character:
+    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_control());
+    /// assert!(!uppercase_g.is_ascii_control());
+    /// assert!(!a.is_ascii_control());
+    /// assert!(!g.is_ascii_control());
+    /// assert!(!zero.is_ascii_control());
+    /// assert!(!percent.is_ascii_control());
+    /// assert!(!space.is_ascii_control());
+    /// assert!(lf.is_ascii_control());
+    /// assert!(esc.is_ascii_control());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            C | Cw => true,
+            _ => false
+        }
+    }
 }
 
 #[lang = "u16"]
@@ -2926,3 +3469,106 @@ impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0"
 
 // Float -> Float
 impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+static ASCII_LOWERCASE_MAP: [u8; 256] = [
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@',
+
+          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z',
+
+                      b'[', b'\\', b']', b'^', b'_',
+    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+static ASCII_UPPERCASE_MAP: [u8; 256] = [
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
+    b'`',
+
+          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z',
+
+                      b'{', b'|', b'}', b'~', 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+enum AsciiCharacterClass {
+    C,  // control
+    Cw, // control whitespace
+    W,  // whitespace
+    D,  // digit
+    L,  // lowercase
+    Lx, // lowercase hex digit
+    U,  // uppercase
+    Ux, // uppercase hex digit
+    P,  // punctuation
+}
+use self::AsciiCharacterClass::*;
+
+static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
+//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
+    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
+    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
+    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
+    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
+    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
+    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
+    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
+    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
+];
diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs
index 4cb6e8405f3..80c48c7b28e 100644
--- a/src/libcore/ops/deref.rs
+++ b/src/libcore/ops/deref.rs
@@ -18,7 +18,7 @@
 /// Implementing `Deref` for smart pointers makes accessing the data behind them
 /// convenient, which is why they implement `Deref`. On the other hand, the
 /// rules regarding `Deref` and [`DerefMut`] were designed specifically to
-/// accomodate smart pointers. Because of this, **`Deref` should only be
+/// accommodate smart pointers. Because of this, **`Deref` should only be
 /// implemented for smart pointers** to avoid confusion.
 ///
 /// For similar reasons, **this trait should never fail**. Failure during
@@ -103,7 +103,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T {
 /// Implementing `DerefMut` for smart pointers makes mutating the data behind
 /// them convenient, which is why they implement `DerefMut`. On the other hand,
 /// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
-/// accomodate smart pointers. Because of this, **`DerefMut` should only be
+/// accommodate smart pointers. Because of this, **`DerefMut` should only be
 /// implemented for smart pointers** to avoid confusion.
 ///
 /// For similar reasons, **this trait should never fail**. Failure during
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 5cd672b03ff..126558e3025 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -517,8 +517,10 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *const u8).is_null() {
             None
         } else {
             Some(&*self)
@@ -1148,8 +1150,10 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *const u8).is_null() {
             None
         } else {
             Some(&*self)
@@ -1272,8 +1276,10 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "ptr_as_ref", since = "1.9.0")]
     #[inline]
-    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> where T: Sized {
-        if self.is_null() {
+    pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> {
+        // Check for null via a cast to a thin pointer, so fat pointers are only
+        // considering their "data" part for null-ness.
+        if (self as *mut u8).is_null() {
             None
         } else {
             Some(&mut *self)
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 5039bef631e..57e5ae28664 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2450,6 +2450,22 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
     mem::transmute(Repr { data: p, len: len })
 }
 
+/// Converts a reference to T into a slice of length 1 (without copying).
+#[unstable(feature = "from_ref", issue = "45703")]
+pub fn from_ref<T>(s: &T) -> &[T] {
+    unsafe {
+        from_raw_parts(s, 1)
+    }
+}
+
+/// Converts a reference to T into a slice of length 1 (without copying).
+#[unstable(feature = "from_ref", issue = "45703")]
+pub fn from_ref_mut<T>(s: &mut T) -> &mut [T] {
+    unsafe {
+        from_raw_parts_mut(s, 1)
+    }
+}
+
 // This function is public only because there is no other way to unit test heapsort.
 #[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "0")]
 #[doc(hidden)]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 53b056d2b8b..cd3dd9ce139 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -927,6 +927,12 @@ impl<T> AtomicPtr<T> {
     }
 }
 
+#[stable(feature = "atomic_from", since = "1.23.0")]
+impl<T> From<*mut T> for AtomicPtr<T> {
+    #[inline]
+    fn from(p: *mut T) -> Self { Self::new(p) }
+}
+
 #[cfg(target_has_atomic = "ptr")]
 macro_rules! atomic_int {
     ($stable:meta, $const_unstable:meta,
@@ -967,6 +973,12 @@ macro_rules! atomic_int {
             }
         }
 
+        #[stable(feature = "atomic_from", since = "1.23.0")]
+        impl From<$int_type> for $atomic_type {
+            #[inline]
+            fn from(v: $int_type) -> Self { Self::new(v) }
+        }
+
         #[$stable_debug]
         impl fmt::Debug for $atomic_type {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index c2d53840f8f..e93e9be0cd5 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -85,6 +85,39 @@ fn test_as_ref() {
             let p = &u as *const isize;
             assert_eq!(p.as_ref().unwrap(), &2);
         }
+
+        // Pointers to unsized types -- slices
+        let s: &mut [u8] = &mut [1, 2, 3];
+        let cs: *const [u8] = s;
+        assert_eq!(cs.as_ref(), Some(&*s));
+
+        let ms: *mut [u8] = s;
+        assert_eq!(ms.as_ref(), Some(&*s));
+
+        let cz: *const [u8] = &[];
+        assert_eq!(cz.as_ref(), Some(&[][..]));
+
+        let mz: *mut [u8] = &mut [];
+        assert_eq!(mz.as_ref(), Some(&[][..]));
+
+        let ncs: *const [u8] = null::<[u8; 3]>();
+        assert_eq!(ncs.as_ref(), None);
+
+        let nms: *mut [u8] = null_mut::<[u8; 3]>();
+        assert_eq!(nms.as_ref(), None);
+
+        // Pointers to unsized types -- trait objects
+        let ci: *const ToString = &3;
+        assert!(ci.as_ref().is_some());
+
+        let mi: *mut ToString = &mut 3;
+        assert!(mi.as_ref().is_some());
+
+        let nci: *const ToString = null::<isize>();
+        assert!(nci.as_ref().is_none());
+
+        let nmi: *mut ToString = null_mut::<isize>();
+        assert!(nmi.as_ref().is_none());
     }
 }
 
@@ -103,6 +136,24 @@ fn test_as_mut() {
             let p = &mut u as *mut isize;
             assert!(p.as_mut().unwrap() == &mut 2);
         }
+
+        // Pointers to unsized types -- slices
+        let s: &mut [u8] = &mut [1, 2, 3];
+        let ms: *mut [u8] = s;
+        assert_eq!(ms.as_mut(), Some(s));
+
+        let mz: *mut [u8] = &mut [];
+        assert_eq!(mz.as_mut(), Some(&mut [][..]));
+
+        let nms: *mut [u8] = null_mut::<[u8; 3]>();
+        assert_eq!(nms.as_mut(), None);
+
+        // Pointers to unsized types -- trait objects
+        let mi: *mut ToString = &mut 3;
+        assert!(mi.as_mut().is_some());
+
+        let nmi: *mut ToString = null_mut::<isize>();
+        assert!(nmi.as_mut().is_none());
     }
 }
 
diff --git a/src/libcore/unit.rs b/src/libcore/unit.rs
new file mode 100644
index 00000000000..087ddf9688a
--- /dev/null
+++ b/src/libcore/unit.rs
@@ -0,0 +1,31 @@
+// 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.
+
+use iter::FromIterator;
+
+/// Collapses all unit items from an iterator into one.
+///
+/// This is more useful when combined with higher-level abstractions, like
+/// collecting to a `Result<(), E>` where you only care about errors:
+///
+/// ```
+/// use std::io::*;
+/// let data = vec![1, 2, 3, 4, 5];
+/// let res: Result<()> = data.iter()
+///     .map(|x| writeln!(stdout(), "{}", x))
+///     .collect();
+/// assert!(res.is_ok());
+/// ```
+#[stable(feature = "unit_from_iter", since = "1.23.0")]
+impl FromIterator<()> for () {
+    fn from_iter<I: IntoIterator<Item=()>>(iter: I) -> Self {
+        iter.into_iter().for_each(|()| {})
+    }
+}
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 4a763d4144e..89ce4bf928a 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -459,10 +459,6 @@ define_dep_nodes!( <'tcx>
     // Represents metadata from an extern crate.
     [input] CrateMetadata(CrateNum),
 
-    // Represents some artifact that we save to disk. Note that these
-    // do not have a def-id as part of their identifier.
-    [] WorkProduct(WorkProductId),
-
     // Represents different phases in the compiler.
     [] RegionScopeTree(DefId),
     [eval_always] Coherence,
@@ -498,7 +494,7 @@ define_dep_nodes!( <'tcx>
     [] SuperPredicatesOfItem(DefId),
     [] TraitDefOfItem(DefId),
     [] AdtDefOfItem(DefId),
-    [] IsDefaultImpl(DefId),
+    [] IsAutoImpl(DefId),
     [] ImplTraitRef(DefId),
     [] ImplPolarity(DefId),
     [] ClosureKind(DefId),
@@ -537,38 +533,19 @@ define_dep_nodes!( <'tcx>
     // The set of impls for a given trait.
     [] TraitImpls(DefId),
 
-    [] AllLocalTraitImpls,
-
-    // Trait selection cache is a little funny. Given a trait
-    // reference like `Foo: SomeTrait<Bar>`, there could be
-    // arbitrarily many def-ids to map on in there (e.g., `Foo`,
-    // `SomeTrait`, `Bar`). We could have a vector of them, but it
-    // requires heap-allocation, and trait sel in general can be a
-    // surprisingly hot path. So instead we pick two def-ids: the
-    // trait def-id, and the first def-id in the input types. If there
-    // is no def-id in the input types, then we use the trait def-id
-    // again. So for example:
-    //
-    // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
-    // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
-    // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
-    // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
-    //
-    // You can see that we map many trait refs to the same
-    // trait-select node.  This is not a problem, it just means
-    // imprecision in our dep-graph tracking.  The important thing is
-    // that for any given trait-ref, we always map to the **same**
-    // trait-select node.
+    [input] AllLocalTraitImpls,
+
     [anon] TraitSelect,
 
     [] ParamEnv(DefId),
     [] DescribeDef(DefId),
-    [] DefSpan(DefId),
+
+    // FIXME(mw): DefSpans are not really inputs since they are derived from
+    // HIR. But at the moment HIR hashing still contains some hacks that allow
+    // to make type debuginfo to be source location independent. Declaring
+    // DefSpan an input makes sure that changes to these are always detected
+    // regardless of HIR hashing.
+    [input] DefSpan(DefId),
     [] LookupStability(DefId),
     [] LookupDeprecationEntry(DefId),
     [] ItemBodyNestedBodies(DefId),
@@ -588,7 +565,7 @@ define_dep_nodes!( <'tcx>
     [eval_always] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
     [input] InScopeTraits(DefIndex),
-    [] ModuleExports(DefId),
+    [input] ModuleExports(DefId),
     [] IsSanitizerRuntime(CrateNum),
     [] IsProfilerRuntime(CrateNum),
     [] GetPanicStrategy(CrateNum),
@@ -598,9 +575,9 @@ define_dep_nodes!( <'tcx>
     [] NativeLibraries(CrateNum),
     [] PluginRegistrarFn(CrateNum),
     [] DeriveRegistrarFn(CrateNum),
-    [] CrateDisambiguator(CrateNum),
-    [] CrateHash(CrateNum),
-    [] OriginalCrateName(CrateNum),
+    [input] CrateDisambiguator(CrateNum),
+    [input] CrateHash(CrateNum),
+    [input] OriginalCrateName(CrateNum),
 
     [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
     [] AllTraitImplementations(CrateNum),
@@ -608,27 +585,27 @@ define_dep_nodes!( <'tcx>
     [] IsDllimportForeignItem(DefId),
     [] IsStaticallyIncludedForeignItem(DefId),
     [] NativeLibraryKind(DefId),
-    [] LinkArgs,
+    [input] LinkArgs,
 
-    [] NamedRegion(DefIndex),
-    [] IsLateBound(DefIndex),
-    [] ObjectLifetimeDefaults(DefIndex),
+    [input] NamedRegion(DefIndex),
+    [input] IsLateBound(DefIndex),
+    [input] ObjectLifetimeDefaults(DefIndex),
 
     [] Visibility(DefId),
     [] DepKind(CrateNum),
-    [] CrateName(CrateNum),
+    [input] CrateName(CrateNum),
     [] ItemChildren(DefId),
     [] ExternModStmtCnum(DefId),
-    [] GetLangItems,
+    [input] GetLangItems,
     [] DefinedLangItems(CrateNum),
     [] MissingLangItems(CrateNum),
     [] ExternConstBody(DefId),
     [] VisibleParentMap,
     [] MissingExternCrateItem(CrateNum),
     [] UsedCrateSource(CrateNum),
-    [] PostorderCnums,
-    [] HasCloneClosures(CrateNum),
-    [] HasCopyClosures(CrateNum),
+    [input] PostorderCnums,
+    [input] HasCloneClosures(CrateNum),
+    [input] HasCopyClosures(CrateNum),
 
     // This query is not expected to have inputs -- as a result, it's
     // not a good candidate for "replay" because it's essentially a
@@ -638,11 +615,11 @@ define_dep_nodes!( <'tcx>
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
 
-    [] Freevars(DefId),
-    [] MaybeUnusedTraitImport(DefId),
+    [input] Freevars(DefId),
+    [input] MaybeUnusedTraitImport(DefId),
     [] MaybeUnusedExternCrates,
     [] StabilityIndex,
-    [] AllCrateNums,
+    [input] AllCrateNums,
     [] ExportedSymbols(CrateNum),
     [eval_always] CollectAndPartitionTranslationItems,
     [] ExportName(DefId),
@@ -650,7 +627,7 @@ define_dep_nodes!( <'tcx>
     [] IsTranslatedFunction(DefId),
     [] CodegenUnit(InternedString),
     [] CompileCodegenUnit(InternedString),
-    [] OutputFilenames,
+    [input] OutputFilenames,
     [anon] NormalizeTy,
     // We use this for most things when incr. comp. is turned off.
     [] Null,
@@ -800,13 +777,6 @@ impl WorkProductId {
             hash: fingerprint
         }
     }
-
-    pub fn to_dep_node(self) -> DepNode {
-        DepNode {
-            kind: DepKind::WorkProduct,
-            hash: self.hash,
-        }
-    }
 }
 
 impl_stable_hash_for!(struct ::dep_graph::WorkProductId {
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index ec709b301eb..1433fa81f33 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use errors::DiagnosticBuilder;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHashingContextProvider};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -44,25 +45,10 @@ pub struct DepGraph {
 }
 
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DepNodeIndex {
-    index: u32,
-}
-
-impl Idx for DepNodeIndex {
-    fn new(idx: usize) -> Self {
-        debug_assert!((idx & 0xFFFF_FFFF) == idx);
-        DepNodeIndex { index: idx as u32 }
-    }
-    fn index(self) -> usize {
-        self.index as usize
-    }
-}
+newtype_index!(DepNodeIndex);
 
 impl DepNodeIndex {
-    const INVALID: DepNodeIndex = DepNodeIndex {
-        index: ::std::u32::MAX,
-    };
+    const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX);
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -342,7 +328,12 @@ impl DepGraph {
     }
 
     pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
-        self.fingerprints.borrow()[dep_node]
+        match self.fingerprints.borrow().get(dep_node) {
+            Some(&fingerprint) => fingerprint,
+            None => {
+                bug!("Could not find current fingerprint for {:?}", dep_node)
+            }
+        }
     }
 
     pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
@@ -520,60 +511,67 @@ impl DepGraph {
                     return None
                 }
                 None => {
-                    if dep_dep_node.kind.is_input() {
-                        // This input does not exist anymore.
-                        debug_assert!(dep_dep_node.extract_def_id(tcx).is_none(),
-                                      "Encountered input {:?} without color",
-                                      dep_dep_node);
-                        debug!("try_mark_green({:?}) - END - dependency {:?} \
-                                was deleted input", dep_node, dep_dep_node);
-                        return None;
+                    // We don't know the state of this dependency. If it isn't
+                    // an input node, let's try to mark it green recursively.
+                    if !dep_dep_node.kind.is_input() {
+                         debug!("try_mark_green({:?}) --- state of dependency {:?} \
+                                 is unknown, trying to mark it green", dep_node,
+                                 dep_dep_node);
+
+                        if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
+                            debug!("try_mark_green({:?}) --- managed to MARK \
+                                    dependency {:?} as green", dep_node, dep_dep_node);
+                            current_deps.push(node_index);
+                            continue;
+                        }
+                    } else if cfg!(debug_assertions) {
+                        match dep_dep_node.kind {
+                            DepKind::Hir |
+                            DepKind::HirBody |
+                            DepKind::CrateMetadata => {
+                                assert!(dep_dep_node.extract_def_id(tcx).is_none(),
+                                    "Input {:?} should have been pre-allocated but wasn't.",
+                                    dep_dep_node);
+                            }
+                            _ => {
+                                // For other kinds of inputs it's OK to be
+                                // forced.
+                            }
+                        }
                     }
 
-                    debug!("try_mark_green({:?}) --- state of dependency {:?} \
-                            is unknown, trying to mark it green", dep_node,
-                            dep_dep_node);
-
-                    // We don't know the state of this dependency. Let's try to
-                    // mark it green.
-                    if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
-                        debug!("try_mark_green({:?}) --- managed to MARK \
-                                dependency {:?} as green", dep_node, dep_dep_node);
-                        current_deps.push(node_index);
-                    } else {
-                        // We failed to mark it green, so we try to force the query.
-                        debug!("try_mark_green({:?}) --- trying to force \
-                                dependency {:?}", dep_node, dep_dep_node);
-                        if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
-                            let dep_dep_node_color = data.colors
-                                                         .borrow()
-                                                         .get(dep_dep_node)
-                                                         .cloned();
-                            match dep_dep_node_color {
-                                Some(DepNodeColor::Green(node_index)) => {
-                                    debug!("try_mark_green({:?}) --- managed to \
-                                            FORCE dependency {:?} to green",
-                                            dep_node, dep_dep_node);
-                                    current_deps.push(node_index);
-                                }
-                                Some(DepNodeColor::Red) => {
-                                    debug!("try_mark_green({:?}) - END - \
-                                            dependency {:?} was red after forcing",
-                                           dep_node,
-                                           dep_dep_node);
-                                    return None
-                                }
-                                None => {
-                                    bug!("try_mark_green() - Forcing the DepNode \
-                                          should have set its color")
-                                }
+                    // We failed to mark it green, so we try to force the query.
+                    debug!("try_mark_green({:?}) --- trying to force \
+                            dependency {:?}", dep_node, dep_dep_node);
+                    if ::ty::maps::force_from_dep_node(tcx, dep_dep_node) {
+                        let dep_dep_node_color = data.colors
+                                                     .borrow()
+                                                     .get(dep_dep_node)
+                                                     .cloned();
+                        match dep_dep_node_color {
+                            Some(DepNodeColor::Green(node_index)) => {
+                                debug!("try_mark_green({:?}) --- managed to \
+                                        FORCE dependency {:?} to green",
+                                        dep_node, dep_dep_node);
+                                current_deps.push(node_index);
+                            }
+                            Some(DepNodeColor::Red) => {
+                                debug!("try_mark_green({:?}) - END - \
+                                        dependency {:?} was red after forcing",
+                                       dep_node,
+                                       dep_dep_node);
+                                return None
+                            }
+                            None => {
+                                bug!("try_mark_green() - Forcing the DepNode \
+                                      should have set its color")
                             }
-                        } else {
-                            // The DepNode could not be forced.
-                            debug!("try_mark_green({:?}) - END - dependency {:?} \
-                                    could not be forced", dep_node, dep_dep_node);
-                            return None
                         }
+                    } else {
+                        // The DepNode could not be forced.
+                        debug!("try_mark_green({:?}) - END - dependency {:?} \
+                                could not be forced", dep_node, dep_dep_node);
+                        return None
                     }
                 }
             }
@@ -600,6 +598,24 @@ impl DepGraph {
                       "DepGraph::try_mark_green() - Duplicate fingerprint \
                       insertion for {:?}", dep_node);
 
+        // ... emitting any stored diagnostic ...
+        {
+            let diagnostics = tcx.on_disk_query_result_cache
+                                 .load_diagnostics(prev_dep_node_index);
+
+            if diagnostics.len() > 0 {
+                let handle = tcx.sess.diagnostic();
+
+                // Promote the previous diagnostics to the current session.
+                tcx.on_disk_query_result_cache
+                   .store_diagnostics(dep_node_index, diagnostics.clone());
+
+                for diagnostic in diagnostics {
+                    DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
+                }
+            }
+        }
+
         // ... and finally storing a "Green" entry in the color map.
         let old_color = data.colors
                             .borrow_mut()
@@ -768,7 +784,30 @@ impl CurrentDepGraph {
             read_set: _,
             reads
         } = popped_node {
-            debug_assert_eq!(node, key);
+            assert_eq!(node, key);
+
+            // If this is an input node, we expect that it either has no
+            // dependencies, or that it just depends on DepKind::CrateMetadata
+            // or DepKind::Krate. This happens for some "thin wrapper queries"
+            // like `crate_disambiguator` which sometimes have zero deps (for
+            // when called for LOCAL_CRATE) or they depend on a CrateMetadata
+            // node.
+            if cfg!(debug_assertions) {
+                if node.kind.is_input() && reads.len() > 0 &&
+                   // FIXME(mw): Special case for DefSpan until Spans are handled
+                   //            better in general.
+                   node.kind != DepKind::DefSpan &&
+                    reads.iter().any(|&i| {
+                        !(self.nodes[i].kind == DepKind::CrateMetadata ||
+                          self.nodes[i].kind == DepKind::Krate)
+                    })
+                {
+                    bug!("Input node {:?} with unexpected reads: {:?}",
+                        node,
+                        reads.iter().map(|&i| self.nodes[i]).collect::<Vec<_>>())
+                }
+            }
+
             self.alloc_node(node, reads)
         } else {
             bug!("pop_task() - Expected regular task to be popped")
@@ -789,6 +828,8 @@ impl CurrentDepGraph {
             read_set: _,
             reads
         } = popped_node {
+            debug_assert!(!kind.is_input());
+
             let mut fingerprint = self.anon_id_seed;
             let mut hasher = StableHasher::new();
 
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index fe0212423f6..a472183698a 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -26,4 +26,4 @@ pub use self::prev::PreviousDepGraph;
 pub use self::query::DepGraphQuery;
 pub use self::safe::AssertDepGraphSafe;
 pub use self::safe::DepGraphSafe;
-pub use self::serialized::SerializedDepGraph;
+pub use self::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 69d23504cda..428f154c1b6 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -16,30 +16,23 @@ use serialize::{self, Encoder, Decoder};
 use std::fmt;
 use std::u32;
 
-#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)]
-pub struct CrateNum(u32);
+newtype_index!(CrateNum
+    {
+        derive[Debug]
+        ENCODABLE = custom
 
-impl Idx for CrateNum {
-    fn new(value: usize) -> Self {
-        assert!(value < (u32::MAX) as usize);
-        CrateNum(value as u32)
-    }
-
-    fn index(self) -> usize {
-        self.0 as usize
-    }
-}
-
-/// Item definitions in the currently-compiled crate would have the CrateNum
-/// LOCAL_CRATE in their DefId.
-pub const LOCAL_CRATE: CrateNum = CrateNum(0);
+        /// Item definitions in the currently-compiled crate would have the CrateNum
+        /// LOCAL_CRATE in their DefId.
+        const LOCAL_CRATE = 0,
 
-/// Virtual crate for builtin macros
-// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
-pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX);
+        /// Virtual crate for builtin macros
+        // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
+        // `CrateNum`s.
+        const BUILTIN_MACROS_CRATE = u32::MAX,
 
-/// A CrateNum value that indicates that something is wrong.
-pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1);
+        /// A CrateNum value that indicates that something is wrong.
+        const INVALID_CRATE = u32::MAX - 1,
+    });
 
 impl CrateNum {
     pub fn new(x: usize) -> CrateNum {
@@ -93,20 +86,17 @@ impl serialize::UseSpecializedDecodable for CrateNum {
 ///
 /// Since the DefIndex is mostly treated as an opaque ID, you probably
 /// don't have to care about these ranges.
-#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
-           RustcDecodable, Hash, Copy)]
-pub struct DefIndex(u32);
+newtype_index!(DefIndex
+    {
+        DEBUG_FORMAT = custom,
 
-impl Idx for DefIndex {
-    fn new(value: usize) -> Self {
-        assert!(value < (u32::MAX) as usize);
-        DefIndex(value as u32)
-    }
+        /// The start of the "high" range of DefIndexes.
+        const DEF_INDEX_HI_START = 1 << 31,
 
-    fn index(self) -> usize {
-        self.0 as usize
-    }
-}
+        /// The crate root is always assigned index 0 by the AST Map code,
+        /// thanks to `NodeCollector::new`.
+        const CRATE_DEF_INDEX = 0,
+    });
 
 impl fmt::Debug for DefIndex {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -119,12 +109,6 @@ impl fmt::Debug for DefIndex {
 
 impl DefIndex {
     #[inline]
-    pub fn new(x: usize) -> DefIndex {
-        assert!(x < (u32::MAX as usize));
-        DefIndex(x as u32)
-    }
-
-    #[inline]
     pub fn from_u32(x: u32) -> DefIndex {
         DefIndex(x)
     }
@@ -162,13 +146,6 @@ impl DefIndex {
     }
 }
 
-/// The start of the "high" range of DefIndexes.
-const DEF_INDEX_HI_START: DefIndex = DefIndex(1 << 31);
-
-/// The crate root is always assigned index 0 by the AST Map code,
-/// thanks to `NodeCollector::new`.
-pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
-
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub enum DefIndexAddressSpace {
     Low = 0,
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index ae25924ab42..c23a5fb1f7e 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -503,7 +503,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             // visit_enum_def() takes care of visiting the Item's NodeId
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemDefaultImpl(_, ref trait_ref) => {
+        ItemAutoImpl(_, ref trait_ref) => {
             visitor.visit_id(item.id);
             visitor.visit_trait_ref(trait_ref)
         }
@@ -520,7 +520,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
-        ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
+        ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 3834852cac5..ba89961adc6 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -96,7 +96,7 @@ pub struct LoweringContext<'a> {
     exported_macros: Vec<hir::MacroDef>,
 
     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
-    trait_default_impl: BTreeMap<DefId, NodeId>,
+    trait_auto_impl: BTreeMap<DefId, NodeId>,
 
     is_generator: bool,
 
@@ -146,7 +146,7 @@ pub fn lower_crate(sess: &Session,
         impl_items: BTreeMap::new(),
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
-        trait_default_impl: BTreeMap::new(),
+        trait_auto_impl: BTreeMap::new(),
         exported_macros: Vec::new(),
         catch_scopes: Vec::new(),
         loop_scopes: Vec::new(),
@@ -198,7 +198,7 @@ impl<'a> LoweringContext<'a> {
                     ItemKind::Union(_, ref generics) |
                     ItemKind::Enum(_, ref generics) |
                     ItemKind::Ty(_, ref generics) |
-                    ItemKind::Trait(_, ref generics, ..) => {
+                    ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics.lifetimes.len();
                         self.lctx.type_def_lifetime_params.insert(def_id, count);
@@ -284,7 +284,7 @@ impl<'a> LoweringContext<'a> {
             bodies: self.bodies,
             body_ids,
             trait_impls: self.trait_impls,
-            trait_default_impl: self.trait_default_impl,
+            trait_auto_impl: self.trait_auto_impl,
         }
     }
 
@@ -838,7 +838,10 @@ impl<'a> LoweringContext<'a> {
                         return n;
                     }
                     assert!(!def_id.is_local());
-                    let n = self.cstore.item_generics_cloned_untracked(def_id).regions.len();
+                    let n = self.cstore
+                                .item_generics_cloned_untracked(def_id, self.sess)
+                                .regions
+                                .len();
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
@@ -1479,14 +1482,14 @@ impl<'a> LoweringContext<'a> {
                 let vdata = self.lower_variant_data(vdata);
                 hir::ItemUnion(vdata, self.lower_generics(generics))
             }
-            ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 let trait_ref = self.lower_trait_ref(trait_ref);
 
                 if let Def::Trait(def_id) = trait_ref.path.def {
-                    self.trait_default_impl.insert(def_id, id);
+                    self.trait_auto_impl.insert(def_id, id);
                 }
 
-                hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
+                hir::ItemAutoImpl(self.lower_unsafety(unsafety),
                                      trait_ref)
             }
             ItemKind::Impl(unsafety,
@@ -1515,10 +1518,11 @@ impl<'a> LoweringContext<'a> {
                               self.lower_ty(ty),
                               new_impl_items)
             }
-            ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
+            ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_bounds(bounds);
                 let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
-                hir::ItemTrait(self.lower_unsafety(unsafety),
+                hir::ItemTrait(self.lower_is_auto(is_auto),
+                               self.lower_unsafety(unsafety),
                                self.lower_generics(generics),
                                bounds,
                                items)
@@ -1741,6 +1745,13 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
+        match a {
+            IsAuto::Yes => hir::IsAuto::Yes,
+            IsAuto::No => hir::IsAuto::No,
+        }
+    }
+
     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
         match u {
             Unsafety::Unsafe => hir::Unsafety::Unsafe,
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 2f4b62dcbf7..5c1e74dcf43 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -71,7 +71,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
                 impl_items: _,
                 bodies: _,
                 trait_impls: _,
-                trait_default_impl: _,
+                trait_auto_impl: _,
                 body_ids: _,
             } = *krate;
 
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 9d49776749b..d8590c1de94 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -104,7 +104,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into
         let def_data = match i.node {
-            ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
+            ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 6418df47952..b30cc0b09c9 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -19,7 +19,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, DefIndexAddressSpace,
                   CRATE_DEF_INDEX};
 use ich::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::stable_hasher::StableHasher;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use session::CrateDisambiguator;
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index a23658664dc..453d30dde75 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -416,6 +416,12 @@ impl<'hir> Map<'hir> {
     /// if the node is a body owner, otherwise returns `None`.
     pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
         if let Some(entry) = self.find_entry(id) {
+            if self.dep_graph.is_fully_enabled() {
+                let hir_id_owner = self.node_to_hir_id(id).owner;
+                let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
+                self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
+            }
+
             if let Some(body_id) = entry.associated_body() {
                 // For item-like things and closures, the associated
                 // body has its own distinct id, and that is returned
@@ -474,16 +480,16 @@ impl<'hir> Map<'hir> {
         self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
-    pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
+    pub fn trait_auto_impl(&self, trait_did: DefId) -> Option<NodeId> {
         self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
 
         // NB: intentionally bypass `self.forest.krate()` so that we
         // do not trigger a read of the whole krate here
-        self.forest.krate.trait_default_impl.get(&trait_did).cloned()
+        self.forest.krate.trait_auto_impl.get(&trait_did).cloned()
     }
 
     pub fn trait_is_auto(&self, trait_did: DefId) -> bool {
-        self.trait_default_impl(trait_did).is_some()
+        self.trait_auto_impl(trait_did).is_some()
     }
 
     /// Get the attributes on the krate. This is preferable to
@@ -530,6 +536,12 @@ impl<'hir> Map<'hir> {
     /// from a node to the root of the ast (unless you get the same id back here
     /// that can happen if the id is not in the map itself or is just weird).
     pub fn get_parent_node(&self, id: NodeId) -> NodeId {
+        if self.dep_graph.is_fully_enabled() {
+            let hir_id_owner = self.node_to_hir_id(id).owner;
+            let def_path_hash = self.definitions.def_path_hash(hir_id_owner);
+            self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
+        }
+
         self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
     }
 
@@ -1140,7 +1152,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemUnion(..) => "union",
                 ItemTrait(..) => "trait",
                 ItemImpl(..) => "impl",
-                ItemDefaultImpl(..) => "default impl",
+                ItemAutoImpl(..) => "default impl",
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index e23e2acefb7..c9b1d70e7b6 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -499,7 +499,7 @@ pub struct Crate {
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
     pub bodies: BTreeMap<BodyId, Body>,
     pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
-    pub trait_default_impl: BTreeMap<DefId, NodeId>,
+    pub trait_auto_impl: BTreeMap<DefId, NodeId>,
 
     /// A list of the body ids written out in the order in which they
     /// appear in the crate. If you're going to process all the bodies
@@ -1500,6 +1500,13 @@ pub struct FnDecl {
     pub has_implicit_self: bool,
 }
 
+/// Is the trait definition an auto trait?
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAuto {
+    Yes,
+    No
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1811,12 +1818,12 @@ pub enum Item_ {
     /// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
     ItemUnion(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
+    ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
 
-    // Default trait implementations
+    /// Auto trait implementations
     ///
     /// `impl Trait for .. {}`
-    ItemDefaultImpl(Unsafety, TraitRef),
+    ItemAutoImpl(Unsafety, TraitRef),
     /// An implementation, eg `impl<A> Trait for Foo { .. }`
     ItemImpl(Unsafety,
              ImplPolarity,
@@ -1844,7 +1851,7 @@ impl Item_ {
             ItemUnion(..) => "union",
             ItemTrait(..) => "trait",
             ItemImpl(..) |
-            ItemDefaultImpl(..) => "item",
+            ItemAutoImpl(..) => "item",
         }
     }
 
@@ -1864,7 +1871,7 @@ impl Item_ {
             ItemEnum(_, ref generics) |
             ItemStruct(_, ref generics) |
             ItemUnion(_, ref generics) |
-            ItemTrait(_, ref generics, _, _) |
+            ItemTrait(_, _, ref generics, _, _) |
             ItemImpl(_, _, _, ref generics, _, _, _)=> generics,
             _ => return None
         })
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 24a0b5fcea9..7d0f26ba34d 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -660,7 +660,7 @@ impl<'a> State<'a> {
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.name, item.span, true)?;
             }
-            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
@@ -717,9 +717,10 @@ impl<'a> State<'a> {
                 }
                 self.bclose(item.span)?;
             }
-            hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
+            hir::ItemTrait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
+                self.print_is_auto(is_auto)?;
                 self.print_unsafety(unsafety)?;
                 self.word_nbsp("trait")?;
                 self.print_name(item.name)?;
@@ -1253,6 +1254,15 @@ impl<'a> State<'a> {
             Fixity::None => (prec + 1, prec + 1),
         };
 
+        let left_prec = match (&lhs.node, op.node) {
+            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
+            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
+            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
+            (&hir::ExprCast { .. }, hir::BinOp_::BiLt) |
+            (&hir::ExprCast { .. }, hir::BinOp_::BiShl) => parser::PREC_FORCE_PAREN,
+            _ => left_prec,
+        };
+
         self.print_expr_maybe_paren(lhs, left_prec)?;
         self.s.space()?;
         self.word_space(op.node.as_str())?;
@@ -2274,6 +2284,13 @@ impl<'a> State<'a> {
             hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
         }
     }
+
+    pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
+        match s {
+            hir::IsAuto::Yes => self.word_nbsp("auto"),
+            hir::IsAuto::No => Ok(()),
+        }
+    }
 }
 
 // Dup'ed from parse::classify, but adapted for the HIR.
diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs
index f3bb3b38566..3d089d8e75f 100644
--- a/src/librustc/ich/fingerprint.rs
+++ b/src/librustc/ich/fingerprint.rs
@@ -30,6 +30,11 @@ impl Fingerprint {
     }
 
     #[inline]
+    pub fn as_value(&self) -> (u64, u64) {
+        (self.0, self.1)
+    }
+
+    #[inline]
     pub fn combine(self, other: Fingerprint) -> Fingerprint {
         // See https://stackoverflow.com/a/27952689 on why this function is
         // implemented this way.
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index d24344e4e21..f204d352842 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -227,6 +227,8 @@ impl<'gcx> StableHashingContext<'gcx> {
         match binop {
             hir::BiAdd |
             hir::BiSub |
+            hir::BiShl |
+            hir::BiShr |
             hir::BiMul => self.overflow_checks_enabled,
 
             hir::BiDiv |
@@ -237,8 +239,6 @@ impl<'gcx> StableHashingContext<'gcx> {
             hir::BiBitXor |
             hir::BiBitAnd |
             hir::BiBitOr |
-            hir::BiShl |
-            hir::BiShr |
             hir::BiEq |
             hir::BiLt |
             hir::BiLe |
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 5a36c420462..6b78cd473be 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -356,33 +356,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Block {
             targeted_by_break,
         } = *self;
 
-        let non_item_stmts = || stmts.iter().filter(|stmt| {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        // If this is a declaration of a nested item, we don't
-                        // want to leave any trace of it in the hash value, not
-                        // even that it exists. Otherwise changing the position
-                        // of nested items would invalidate the containing item
-                        // even though that does not constitute a semantic
-                        // change.
-                        hir::DeclItem(_) => false,
-                        hir::DeclLocal(_) => true
-                    }
-                }
-                hir::StmtExpr(..) |
-                hir::StmtSemi(..) => true
-            }
-        });
-
-        let count = non_item_stmts().count();
-
-        count.hash_stable(hcx, hasher);
-
-        for stmt in non_item_stmts() {
-            stmt.hash_stable(hcx, hasher);
-        }
-
+        stmts.hash_stable(hcx, hasher);
         expr.hash_stable(hcx, hasher);
         rules.hash_stable(hcx, hasher);
         span.hash_stable(hcx, hasher);
@@ -898,7 +872,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Item {
             hir::ItemForeignMod(..)  |
             hir::ItemGlobalAsm(..)   |
             hir::ItemMod(..)         |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTrait(..)       |
             hir::ItemImpl(..)        |
             hir::ItemTy(..)          |
@@ -944,8 +918,8 @@ impl_stable_hash_for!(enum hir::Item_ {
     ItemEnum(enum_def, generics),
     ItemStruct(variant_data, generics),
     ItemUnion(variant_data, generics),
-    ItemTrait(unsafety, generics, bounds, item_refs),
-    ItemDefaultImpl(unsafety, trait_ref),
+    ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
+    ItemAutoImpl(unsafety, trait_ref),
     ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
 });
 
@@ -1126,6 +1100,10 @@ impl_stable_hash_for!(enum hir::Mutability {
     MutImmutable
 });
 
+impl_stable_hash_for!(enum hir::IsAuto {
+    Yes,
+    No
+});
 
 impl_stable_hash_for!(enum hir::Unsafety {
     Unsafe,
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 4bda89690b7..05436201e7a 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -62,7 +62,8 @@ for mir::Terminator<'gcx> {
             mir::TerminatorKind::Drop { .. } |
             mir::TerminatorKind::DropAndReplace { .. } |
             mir::TerminatorKind::Yield { .. } |
-            mir::TerminatorKind::Call { .. } => false,
+            mir::TerminatorKind::Call { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => false,
         };
 
         if hash_spans_unconditionally {
@@ -210,6 +211,12 @@ for mir::TerminatorKind<'gcx> {
                 target.hash_stable(hcx, hasher);
                 cleanup.hash_stable(hcx, hasher);
             }
+            mir::TerminatorKind::FalseEdges { ref real_target, ref imaginary_targets } => {
+                real_target.hash_stable(hcx, hasher);
+                for target in imaginary_targets {
+                    target.hash_stable(hcx, hasher);
+                }
+            }
         }
     }
 }
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 799e790b85f..fea4e283db1 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -364,6 +364,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
             end_pos: _,
             ref lines,
             ref multibyte_chars,
+            ref non_narrow_chars,
         } = *self;
 
         name.hash_stable(hcx, hasher);
@@ -389,6 +390,12 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for FileMap {
         for &char_pos in multibyte_chars.iter() {
             stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
         }
+
+        let non_narrow_chars = non_narrow_chars.borrow();
+        non_narrow_chars.len().hash_stable(hcx, hasher);
+        for &char_pos in non_narrow_chars.iter() {
+            stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
+        }
     }
 }
 
@@ -408,3 +415,12 @@ fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
 
     (pos.0 - filemap_start.0, bytes as u32)
 }
+
+fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
+                          filemap_start: ::syntax_pos::BytePos)
+                          -> (u32, u32) {
+    let pos = swc.pos();
+    let width = swc.width();
+
+    (pos.0 - filemap_start.0, width as u32)
+}
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 48d3017f597..e7627b110fa 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -731,13 +731,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::TraitDef {
             def_id: _,
             unsafety,
             paren_sugar,
-            has_default_impl,
+            has_auto_impl,
             def_path_hash,
         } = *self;
 
         unsafety.hash_stable(hcx, hasher);
         paren_sugar.hash_stable(hcx, hasher);
-        has_default_impl.hash_stable(hcx, hasher);
+        has_auto_impl.hash_stable(hcx, hasher);
         def_path_hash.hash_stable(hcx, hasher);
     }
 }
@@ -856,7 +856,7 @@ for traits::Vtable<'gcx, N> where N: HashStable<StableHashingContext<'gcx>> {
 
         match self {
             &VtableImpl(ref table_impl) => table_impl.hash_stable(hcx, hasher),
-            &VtableDefaultImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
+            &VtableAutoImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
             &VtableParam(ref table_param) => table_param.hash_stable(hcx, hasher),
             &VtableObject(ref table_obj) => table_obj.hash_stable(hcx, hasher),
             &VtableBuiltin(ref table_builtin) => table_builtin.hash_stable(hcx, hasher),
@@ -884,11 +884,11 @@ for traits::VtableImplData<'gcx, N> where N: HashStable<StableHashingContext<'gc
 }
 
 impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableDefaultImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
+for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        let traits::VtableDefaultImplData {
+        let traits::VtableAutoImplData {
             trait_def_id,
             ref nested,
         } = *self;
diff --git a/src/librustc/infer/README.md b/src/librustc/infer/README.md
index b4075f69730..6c1478531f1 100644
--- a/src/librustc/infer/README.md
+++ b/src/librustc/infer/README.md
@@ -90,7 +90,7 @@ holds trivially because A==B.  However, we have now lost some
 flexibility, because perhaps the user intended for A and B to end up
 as different types and not the same type.
 
-Pictorally, what this does is to take two distinct variables with
+Pictorially, what this does is to take two distinct variables with
 (hopefully not completely) distinct type ranges and produce one with
 the intersection.
 
diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs
index ee30db26255..d7e0877d95c 100644
--- a/src/librustc/infer/error_reporting/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/different_lifetimes.rs
@@ -21,25 +21,42 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::error_reporting::util::AnonymousArgInfo;
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    // This method prints the error message for lifetime errors when both the concerned regions
-    // are anonymous.
-    // Consider a case where we have
-    // fn foo(x: &mut Vec<&u8>, y: &u8)
-    //    { x.push(y); }.
-    // The example gives
-    // fn foo(x: &mut Vec<&u8>, y: &u8) {
-    //                    ---      --- these references are declared with different lifetimes...
-    //            x.push(y);
-    //            ^ ...but data from `y` flows into `x` here
-    // It has been extended for the case of structs too.
-    // Consider the example
-    // struct Ref<'a> { x: &'a u32 }
-    // fn foo(mut x: Vec<Ref>, y: Ref) {
-    //                   ---      --- these structs are declared with different lifetimes...
-    //               x.push(y);
-    //               ^ ...but data from `y` flows into `x` here
-    // }
-    // It will later be extended to trait objects.
+    /// Print the error message for lifetime errors when both the concerned regions are anonymous.
+    ///
+    /// Consider a case where we have
+    ///
+    /// ```no_run
+    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
+    ///     x.push(y);
+    /// }
+    /// ```
+    ///
+    /// The example gives
+    ///
+    /// ```text
+    /// fn foo(x: &mut Vec<&u8>, y: &u8) {
+    ///                    ---      --- these references are declared with different lifetimes...
+    ///     x.push(y);
+    ///     ^ ...but data from `y` flows into `x` here
+    /// ```
+    ///
+    /// It has been extended for the case of structs too.
+    ///
+    /// Consider the example
+    ///
+    /// ```no_run
+    /// struct Ref<'a> { x: &'a u32 }
+    /// ```
+    ///
+    /// ```text
+    /// fn foo(mut x: Vec<Ref>, y: Ref) {
+    ///                   ---      --- these structs are declared with different lifetimes...
+    ///     x.push(y);
+    ///     ^ ...but data from `y` flows into `x` here
+    /// }
+    /// ````
+    ///
+    /// It will later be extended to trait objects.
     pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 895894a0bb2..e9916bd77e7 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -66,7 +66,7 @@ use hir::map as hir_map;
 use hir::def_id::DefId;
 use middle::region;
 use traits::{ObligationCause, ObligationCauseCode};
-use ty::{self, Region, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants};
 use ty::error::TypeError;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
@@ -262,6 +262,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                 errors: &Vec<RegionResolutionError<'tcx>>) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
+        if self.tcx.sess.opts.debugging_opts.nll {
+            for error in errors {
+                match *error {
+                    RegionResolutionError::ConcreteFailure(ref origin, ..) |
+                    RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
+                        self.tcx.sess.span_warn(
+                            origin.span(),
+                            "not reporting region error due to -Znll");
+                    }
+
+                    RegionResolutionError::SubSupConflict(ref rvo, ..) => {
+                        self.tcx.sess.span_warn(
+                            rvo.span(),
+                            "not reporting region error due to -Znll");
+                    }
+                }
+            }
+
+            return;
+        }
+
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
         let errors = self.process_errors(errors);
@@ -673,14 +694,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                          values: Option<ValuePairs<'tcx>>,
                          terr: &TypeError<'tcx>)
     {
-        let (expected_found, is_simple_error) = match values {
-            None => (None, false),
+        let (expected_found, exp_found, is_simple_error) = match values {
+            None => (None, None, false),
             Some(values) => {
-                let is_simple_error = match values {
+                let (is_simple_error, exp_found) = match values {
                     ValuePairs::Types(exp_found) => {
-                        exp_found.expected.is_primitive() && exp_found.found.is_primitive()
+                        let is_simple_err = exp_found.expected.is_primitive()
+                            && exp_found.found.is_primitive();
+
+                        (is_simple_err, Some(exp_found))
                     }
-                    _ => false,
+                    _ => (false, None),
                 };
                 let vals = match self.values_str(&values) {
                     Some((expected, found)) => Some((expected, found)),
@@ -690,12 +714,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         return
                     }
                 };
-                (vals, is_simple_error)
+                (vals, exp_found, is_simple_error)
             }
         };
 
         let span = cause.span;
 
+        diag.span_label(span, terr.to_string());
+        if let Some((sp, msg)) = secondary_span {
+            diag.span_label(sp, msg);
+        }
+
         if let Some((expected, found)) = expected_found {
             match (terr, is_simple_error, expected == found) {
                 (&TypeError::Sorts(ref values), false, true) => {
@@ -704,18 +733,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         &format!(" ({})", values.expected.sort_string(self.tcx)),
                         &format!(" ({})", values.found.sort_string(self.tcx)));
                 }
-                (_, false,  _) => {
+                (_, false, _) => {
+                    if let Some(exp_found) = exp_found {
+                        let (def_id, ret_ty) = match exp_found.found.sty {
+                            TypeVariants::TyFnDef(def, _) => {
+                                (Some(def), Some(self.tcx.fn_sig(def).output()))
+                            }
+                            _ => (None, None)
+                        };
+
+                        let exp_is_struct = match exp_found.expected.sty {
+                            TypeVariants::TyAdt(def, _) => def.is_struct(),
+                            _ => false
+                        };
+
+                        if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
+                            if exp_is_struct && exp_found.expected == ret_ty.0 {
+                                let message = format!(
+                                    "did you mean `{}(/* fields */)`?",
+                                    self.tcx.item_path_str(def_id)
+                                );
+                                diag.span_label(cause.span, message);
+                            }
+                        }
+                    }
+
                     diag.note_expected_found(&"type", expected, found);
                 }
                 _ => (),
             }
         }
 
-        diag.span_label(span, terr.to_string());
-        if let Some((sp, msg)) = secondary_span {
-            diag.span_label(sp, msg);
-        }
-
         self.note_error_origin(diag, &cause);
         self.check_and_note_conflicting_crates(diag, terr, span);
         self.tcx.note_and_explain_type_err(diag, terr, span);
diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs
index 80fb4ce8e03..6d3b9507840 100644
--- a/src/librustc/infer/error_reporting/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs
@@ -16,18 +16,15 @@ use infer::region_inference::RegionResolutionError;
 use ty;
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    // This method generates the error message for the case when
-    // the function arguments consist of a named region and an anonymous
-    // region and corresponds to `ConcreteFailure(..)`
+    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
+    /// an anonymous region, emit an descriptive diagnostic error.
     pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
             _ => return false, // inapplicable
         };
 
-        debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})",
-               sub,
-               sup);
+        debug!("try_report_named_anon_conflict(sub={:?}, sup={:?})", sub, sup);
 
         // Determine whether the sub and sup consist of one named region ('a)
         // and one anonymous (elided) region. If so, find the parameter arg
@@ -53,10 +50,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             };
 
         debug!("try_report_named_anon_conflict: named = {:?}", named);
-        debug!("try_report_named_anon_conflict: anon_arg_info = {:?}",
-               anon_arg_info);
-        debug!("try_report_named_anon_conflict: region_info = {:?}",
-               region_info);
+        debug!("try_report_named_anon_conflict: anon_arg_info = {:?}", anon_arg_info);
+        debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);
 
         let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
                                                                        anon_arg_info.arg_ty,
@@ -101,6 +96,5 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 .span_label(span, format!("lifetime `{}` required", named))
                 .emit();
         return true;
-
     }
 }
diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs
index 47db3f1b792..6bcd98a7a68 100644
--- a/src/librustc/infer/error_reporting/util.rs
+++ b/src/librustc/infer/error_reporting/util.rs
@@ -221,6 +221,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     _ => false,
                 }
             }
+            ty::ReEarlyBound(_) => true,
             _ => false,
         }
     }
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 0d02420457e..6736751a5a2 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -155,7 +155,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
                                .filter(|&&r| !skol_resolution_map.contains_key(r))
                                .cloned()
                                .next()
-                               .expect("no representative region");
+                               .unwrap_or_else(|| {
+                                   bug!("no representative region for `{:?}` in `{:?}`",
+                                        skol, regions)
+                               });
 
                     (skol, representative)
                 })
diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs
index 5cf6aa350bd..49f57d9aef5 100644
--- a/src/librustc/infer/region_inference/graphviz.rs
+++ b/src/librustc/infer/region_inference/graphviz.rs
@@ -19,6 +19,7 @@
 use graphviz as dot;
 
 use hir::def_id::DefIndex;
+use rustc_data_structures::indexed_vec::Idx;
 use ty;
 use middle::free_region::RegionRelations;
 use middle::region;
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 0cec26d339c..498e1aa3520 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -46,6 +46,7 @@
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
+#![feature(inclusive_range_syntax)]
 #![cfg_attr(windows, feature(libc))]
 #![feature(macro_vis_matcher)]
 #![feature(never_type)]
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 52dcbfdedef..d648099d74d 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -33,11 +33,12 @@ pub use self::LintSource::*;
 
 use std::rc::Rc;
 
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 use hir::def_id::{CrateNum, LOCAL_CRATE};
 use hir::intravisit::{self, FnKind};
 use hir;
 use session::Session;
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 use std::hash;
 use syntax::ast;
@@ -463,6 +464,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
         }
     }
 
+    err.code(DiagnosticId::Lint(name));
+
     // Check for future incompatibility lints and issue a stronger warning.
     let lints = sess.lint_store.borrow();
     if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index f4ba7890b17..628538b41c5 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -273,7 +273,7 @@ pub trait CrateStore {
     fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
     fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
     fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics;
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
     fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
@@ -327,7 +327,7 @@ impl CrateStore for DummyCrateStore {
         { bug!("crate_data_as_rc_any") }
     // item info
     fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics
         { bug!("item_generics_cloned") }
 
     // trait/impl-item info
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 259794e9d0e..a42ff543227 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -562,7 +562,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
-                hir::ItemDefaultImpl(..) |
+                hir::ItemAutoImpl(..) |
                 hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
                 _ => item.span,
             };
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index 49a241b86e0..3bcdc4f7e2c 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -182,6 +182,19 @@ impl<'tcx> FreeRegionMap<'tcx> {
         debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
         result
     }
+
+    /// Returns all regions that are known to outlive `r_a`. For
+    /// example, in a function:
+    ///
+    /// ```
+    /// fn foo<'a, 'b: 'a, 'c: 'b>() { .. }
+    /// ```
+    ///
+    /// if `r_a` represents `'a`, this function would return `{'b, 'c}`.
+    pub fn regions_that_outlive<'a, 'gcx>(&self, r_a: Region<'tcx>) -> Vec<&Region<'tcx>> {
+        assert!(is_free(r_a));
+        self.relation.greater_than(&r_a)
+    }
 }
 
 fn is_free(r: Region) -> bool {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 679c4f17a6c..a38b37ff745 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -211,6 +211,7 @@ language_item_table! {
     CharImplItem,                    "char",                    char_impl;
     StrImplItem,                     "str",                     str_impl;
     SliceImplItem,                   "slice",                   slice_impl;
+    SliceU8ImplItem,                 "slice_u8",                slice_u8_impl;
     ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
     MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
     I8ImplItem,                      "i8",                      i8_impl;
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 2037bc01a5b..d5f26d1117c 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -270,7 +270,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) |
                     hir::ItemStruct(..) | hir::ItemEnum(..) |
-                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
+                    hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
                     hir::ItemGlobalAsm(..) => {}
                 }
             }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index fa4ee7c0092..89707839144 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -158,8 +158,8 @@ pub struct BlockRemainder {
 
 newtype_index!(FirstStatementIndex
     {
-        DEBUG_NAME = "",
-        MAX = SCOPE_DATA_REMAINDER_MAX,
+        pub idx
+        MAX = SCOPE_DATA_REMAINDER_MAX
     });
 
 impl From<ScopeData> for Scope {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index ee0e580920e..ffd06ee8a2e 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -313,7 +313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             hir::ItemExternCrate(_) |
             hir::ItemUse(..) |
             hir::ItemMod(..) |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemForeignMod(..) |
             hir::ItemGlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
@@ -332,7 +332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             hir::ItemEnum(_, ref generics) |
             hir::ItemStruct(_, ref generics) |
             hir::ItemUnion(_, ref generics) |
-            hir::ItemTrait(_, ref generics, ..) |
+            hir::ItemTrait(_, _, ref generics, ..) |
             hir::ItemImpl(_, _, _, ref generics, ..) => {
                 // These kinds of items have only early bound lifetime parameters.
                 let mut index = if let hir::ItemTrait(..) = item.node {
@@ -688,7 +688,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
             hir::ItemUnion(_, ref generics) |
             hir::ItemEnum(_, ref generics) |
             hir::ItemTy(_, ref generics) |
-            hir::ItemTrait(_, ref generics, ..) => {
+            hir::ItemTrait(_, _, ref generics, ..) => {
                 let result = object_lifetime_defaults_for_item(hir_map, generics);
 
                 // Debugging aid.
@@ -844,7 +844,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 index += 1; // Self comes first.
             }
             match parent.node {
-                hir::ItemTrait(_, ref generics, ..) |
+                hir::ItemTrait(_, _, ref generics, ..) |
                 hir::ItemImpl(_, _, _, ref generics, ..) => {
                     index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
                 }
@@ -1001,8 +1001,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 &map.object_lifetime_defaults[&id]
             } else {
                 let cstore = self.cstore;
+                let sess = self.sess;
                 self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
-                    cstore.item_generics_cloned_untracked(def_id).types.into_iter().map(|def| {
+                    cstore.item_generics_cloned_untracked(def_id, sess)
+                          .types
+                          .into_iter()
+                          .map(|def| {
                         def.object_lifetime_default
                     }).collect()
                 })
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index f5a3c1989cf..2fc27de137f 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -417,7 +417,7 @@ pub enum BorrowKind {
 
 newtype_index!(Local
     {
-        DEBUG_NAME = "_",
+        DEBUG_FORMAT = "_{}",
         const RETURN_POINTER = 0,
     });
 
@@ -553,7 +553,7 @@ pub struct UpvarDecl {
 ///////////////////////////////////////////////////////////////////////////
 // BasicBlock
 
-newtype_index!(BasicBlock { DEBUG_NAME = "bb" });
+newtype_index!(BasicBlock { DEBUG_FORMAT = "bb{}" });
 
 ///////////////////////////////////////////////////////////////////////////
 // BasicBlockData and Terminator
@@ -682,6 +682,11 @@ pub enum TerminatorKind<'tcx> {
 
     /// Indicates the end of the dropping of a generator
     GeneratorDrop,
+
+    FalseEdges {
+        real_target: BasicBlock,
+        imaginary_targets: Vec<BasicBlock>
+    },
 }
 
 impl<'tcx> Terminator<'tcx> {
@@ -731,6 +736,11 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(),
             Assert { ref target, .. } => slice::ref_slice(target).into_cow(),
+            FalseEdges { ref real_target, ref imaginary_targets } => {
+                let mut s = vec![*real_target];
+                s.extend_from_slice(imaginary_targets);
+                s.into_cow()
+            }
         }
     }
 
@@ -757,7 +767,12 @@ impl<'tcx> TerminatorKind<'tcx> {
                 vec![target]
             }
             Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind],
-            Assert { ref mut target, .. } => vec![target]
+            Assert { ref mut target, .. } => vec![target],
+            FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
+                let mut s = vec![real_target];
+                s.extend(imaginary_targets.iter_mut());
+                s
+            }
         }
     }
 }
@@ -874,7 +889,8 @@ impl<'tcx> TerminatorKind<'tcx> {
                 }
 
                 write!(fmt, ")")
-            }
+            },
+            FalseEdges { .. } => write!(fmt, "falseEdges")
         }
     }
 
@@ -910,7 +926,12 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             Assert { cleanup: None, .. } => vec!["".into()],
             Assert { .. } =>
-                vec!["success".into_cow(), "unwind".into_cow()]
+                vec!["success".into_cow(), "unwind".into_cow()],
+            FalseEdges { ref imaginary_targets, .. } => {
+                let mut l = vec!["real".into()];
+                l.resize(imaginary_targets.len() + 1, "imaginary".into());
+                l
+            }
         }
     }
 }
@@ -1135,7 +1156,7 @@ pub type LvalueProjection<'tcx> = Projection<'tcx, Lvalue<'tcx>, Local, Ty<'tcx>
 /// and the index is a local.
 pub type LvalueElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
 
-newtype_index!(Field { DEBUG_NAME = "field" });
+newtype_index!(Field { DEBUG_FORMAT = "field[{}]" });
 
 impl<'tcx> Lvalue<'tcx> {
     pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
@@ -1202,7 +1223,7 @@ impl<'tcx> Debug for Lvalue<'tcx> {
 
 newtype_index!(VisibilityScope
     {
-        DEBUG_NAME = "scope",
+        DEBUG_FORMAT = "scope[{}]",
         const ARGUMENT_VISIBILITY_SCOPE = 0,
     });
 
@@ -1529,7 +1550,8 @@ pub struct Constant<'tcx> {
     pub literal: Literal<'tcx>,
 }
 
-newtype_index!(Promoted { DEBUG_NAME = "promoted" });
+newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });
+
 
 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum Literal<'tcx> {
@@ -1637,6 +1659,14 @@ impl fmt::Debug for Location {
 }
 
 impl Location {
+    /// Returns the location immediately after this one within the enclosing block.
+    ///
+    /// Note that if this location represents a terminator, then the
+    /// resulting location would be out of bounds and invalid.
+    pub fn successor_within_block(&self) -> Location {
+        Location { block: self.block, statement_index: self.statement_index + 1 }
+    }
+
     pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -> bool {
         if self.block == other.block {
             self.statement_index <= other.statement_index
@@ -1870,6 +1900,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             Resume => Resume,
             Return => Return,
             Unreachable => Unreachable,
+            FalseEdges { real_target, ref imaginary_targets } =>
+                FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() }
         };
         Terminator {
             source_info: self.source_info,
@@ -1909,7 +1941,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             Resume |
             Return |
             GeneratorDrop |
-            Unreachable => false
+            Unreachable |
+            FalseEdges { .. } => false
         }
     }
 }
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index f29405e6650..6c90a5f38d0 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -39,13 +39,13 @@ pub enum MirSource {
     GeneratorDrop(NodeId),
 }
 
-impl<'a, 'tcx> MirSource {
-    pub fn from_local_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> MirSource {
+impl<'a, 'gcx, 'tcx> MirSource {
+    pub fn from_local_def_id(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> MirSource {
         let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
         Self::from_node(tcx, id)
     }
 
-    pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
+    pub fn from_node(tcx: TyCtxt<'a, 'gcx, 'tcx>, id: NodeId) -> MirSource {
         use hir::*;
 
         // Handle constants in enum discriminants, types, and repeat expressions.
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 63652980f9b..00863abc84d 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -209,7 +209,7 @@ macro_rules! make_mir_visitor {
 
             fn visit_ty(&mut self,
                         ty: & $($mutability)* Ty<'tcx>,
-                        _: Lookup) {
+                        _: TyContext) {
                 self.super_ty(ty);
             }
 
@@ -256,8 +256,9 @@ macro_rules! make_mir_visitor {
             }
 
             fn visit_local_decl(&mut self,
+                                local: Local,
                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
-                self.super_local_decl(local_decl);
+                self.super_local_decl(local, local_decl);
             }
 
             fn visit_local(&mut self,
@@ -291,14 +292,14 @@ macro_rules! make_mir_visitor {
                     self.visit_visibility_scope_data(scope);
                 }
 
-                let lookup = Lookup::Src(SourceInfo {
+                let lookup = TyContext::SourceInfo(SourceInfo {
                     span: mir.span,
                     scope: ARGUMENT_VISIBILITY_SCOPE,
                 });
                 self.visit_ty(&$($mutability)* mir.return_ty, lookup);
 
-                for local_decl in &$($mutability)* mir.local_decls {
-                    self.visit_local_decl(local_decl);
+                for local in mir.local_decls.indices() {
+                    self.visit_local_decl(local, & $($mutability)* mir.local_decls[local]);
                 }
 
                 self.visit_span(&$($mutability)* mir.span);
@@ -359,7 +360,8 @@ macro_rules! make_mir_visitor {
                         for operand in lvalues {
                             self.visit_lvalue(& $($mutability)* operand.lval,
                                               LvalueContext::Validate, location);
-                            self.visit_ty(& $($mutability)* operand.ty, Lookup::Loc(location));
+                            self.visit_ty(& $($mutability)* operand.ty,
+                                          TyContext::Location(location));
                         }
                     }
                     StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
@@ -421,7 +423,7 @@ macro_rules! make_mir_visitor {
                                                 ref values,
                                                 ref targets } => {
                         self.visit_operand(discr, source_location);
-                        self.visit_ty(switch_ty, Lookup::Loc(source_location));
+                        self.visit_ty(switch_ty, TyContext::Location(source_location));
                         for value in &values[..] {
                             self.visit_const_int(value, source_location);
                         }
@@ -486,8 +488,15 @@ macro_rules! make_mir_visitor {
                         self.visit_operand(value, source_location);
                         self.visit_branch(block, resume);
                         drop.map(|t| self.visit_branch(block, t));
+
                     }
 
+                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+                        self.visit_branch(block, real_target);
+                        for target in imaginary_targets {
+                            self.visit_branch(block, *target);
+                        }
+                    }
                 }
             }
 
@@ -538,7 +547,7 @@ macro_rules! make_mir_visitor {
                                  ref $($mutability)* operand,
                                  ref $($mutability)* ty) => {
                         self.visit_operand(operand, location);
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
 
                     Rvalue::BinaryOp(_bin_op,
@@ -560,7 +569,7 @@ macro_rules! make_mir_visitor {
                     }
 
                     Rvalue::NullaryOp(_op, ref $($mutability)* ty) => {
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
 
                     Rvalue::Aggregate(ref $($mutability)* kind,
@@ -568,7 +577,7 @@ macro_rules! make_mir_visitor {
                         let kind = &$($mutability)* **kind;
                         match *kind {
                             AggregateKind::Array(ref $($mutability)* ty) => {
-                                self.visit_ty(ty, Lookup::Loc(location));
+                                self.visit_ty(ty, TyContext::Location(location));
                             }
                             AggregateKind::Tuple => {
                             }
@@ -638,7 +647,7 @@ macro_rules! make_mir_visitor {
                     ref $($mutability)* ty,
                 } = *static_;
                 self.visit_def_id(def_id, location);
-                self.visit_ty(ty, Lookup::Loc(location));
+                self.visit_ty(ty, TyContext::Location(location));
             }
 
             fn super_projection(&mut self,
@@ -668,7 +677,7 @@ macro_rules! make_mir_visitor {
                     ProjectionElem::Subslice { from: _, to: _ } => {
                     }
                     ProjectionElem::Field(_field, ref $($mutability)* ty) => {
-                        self.visit_ty(ty, Lookup::Loc(location));
+                        self.visit_ty(ty, TyContext::Location(location));
                     }
                     ProjectionElem::Index(ref $($mutability)* local) => {
                         self.visit_local(local, LvalueContext::Consume, location);
@@ -683,6 +692,7 @@ macro_rules! make_mir_visitor {
             }
 
             fn super_local_decl(&mut self,
+                                local: Local,
                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
                 let LocalDecl {
                     mutability: _,
@@ -694,7 +704,10 @@ macro_rules! make_mir_visitor {
                     is_user_variable: _,
                 } = *local_decl;
 
-                self.visit_ty(ty, Lookup::Src(*source_info));
+                self.visit_ty(ty, TyContext::LocalDecl {
+                    local,
+                    source_info: *source_info,
+                });
                 self.visit_source_info(source_info);
                 self.visit_visibility_scope(lexical_scope);
             }
@@ -718,7 +731,7 @@ macro_rules! make_mir_visitor {
                 } = *constant;
 
                 self.visit_span(span);
-                self.visit_ty(ty, Lookup::Loc(location));
+                self.visit_ty(ty, TyContext::Location(location));
                 self.visit_literal(literal, location);
             }
 
@@ -796,10 +809,21 @@ macro_rules! make_mir_visitor {
 make_mir_visitor!(Visitor,);
 make_mir_visitor!(MutVisitor,mut);
 
+/// Extra information passed to `visit_ty` and friends to give context
+/// about where the type etc appears.
 #[derive(Copy, Clone, Debug)]
-pub enum Lookup {
-    Loc(Location),
-    Src(SourceInfo),
+pub enum TyContext {
+    LocalDecl {
+        /// The index of the local variable we are visiting.
+        local: Local,
+
+        /// The source location where this local variable was declared.
+        source_info: SourceInfo,
+    },
+
+    Location(Location),
+
+    SourceInfo(SourceInfo),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 0f8312abc3f..ffb8144e07e 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -138,6 +138,34 @@ impl OutputType {
         }
     }
 
+    fn from_shorthand(shorthand: &str) -> Option<Self> {
+        Some(match shorthand {
+             "asm" => OutputType::Assembly,
+             "llvm-ir" => OutputType::LlvmAssembly,
+             "mir" => OutputType::Mir,
+             "llvm-bc" => OutputType::Bitcode,
+             "obj" => OutputType::Object,
+             "metadata" => OutputType::Metadata,
+             "link" => OutputType::Exe,
+             "dep-info" => OutputType::DepInfo,
+            _ => return None,
+        })
+    }
+
+    fn shorthands_display() -> String {
+        format!(
+            "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
+            OutputType::Bitcode.shorthand(),
+            OutputType::Assembly.shorthand(),
+            OutputType::LlvmAssembly.shorthand(),
+            OutputType::Mir.shorthand(),
+            OutputType::Object.shorthand(),
+            OutputType::Metadata.shorthand(),
+            OutputType::Exe.shorthand(),
+            OutputType::DepInfo.shorthand(),
+        )
+    }
+
     pub fn extension(&self) -> &'static str {
         match *self {
             OutputType::Bitcode => "bc",
@@ -155,7 +183,7 @@ impl OutputType {
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum ErrorOutputType {
     HumanReadable(ColorConfig),
-    Json,
+    Json(bool),
     Short(ColorConfig),
 }
 
@@ -368,6 +396,7 @@ pub enum PrintRequest {
     TargetFeatures,
     RelocationModels,
     CodeModels,
+    TlsModels,
     TargetSpec,
     NativeStaticLibs,
 }
@@ -410,7 +439,7 @@ impl_stable_hash_for!(struct self::OutputFilenames {
     outputs
 });
 
-pub const RUST_CGU_EXT: &str = "rust-cgu";
+pub const RUST_CGU_EXT: &str = "rcgu";
 
 impl OutputFilenames {
     pub fn path(&self, flavor: OutputType) -> PathBuf {
@@ -1017,6 +1046,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "print high-level information about incremental reuse (or the lack thereof)"),
     incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
         "dump hash information in textual format to stdout"),
+    incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
+        "verify incr. comp. hashes of green query instances"),
     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],
@@ -1104,6 +1135,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "enable ThinLTO when possible"),
     inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "control whether #[inline] functions are in all cgus"),
+    tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
+         "choose the TLS model to use (rustc --print tls-models for details)"),
+    saturating_float_casts: bool = (false, parse_bool, [TRACKED],
+        "make casts between integers and floats safe: clip out-of-range inputs to the min/max \
+         integer or to infinity respectively, and turn `NAN` into 0 when casting to integers"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1330,7 +1366,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                                print on stdout",
                      "[crate-name|file-names|sysroot|cfg|target-list|\
                        target-cpus|target-features|relocation-models|\
-                       code-models|target-spec-json|native-static-libs]"),
+                       code-models|tls-models|target-spec-json|native-static-libs]"),
         opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
         opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
         opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
@@ -1433,7 +1469,8 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     let error_format = if matches.opts_present(&["error-format".to_owned()]) {
         match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
             Some("human") => ErrorOutputType::HumanReadable(color),
-            Some("json")  => ErrorOutputType::Json,
+            Some("json")  => ErrorOutputType::Json(false),
+            Some("pretty-json") => ErrorOutputType::Json(true),
             Some("short") => ErrorOutputType::Short(color),
 
             None => ErrorOutputType::HumanReadable(color),
@@ -1472,26 +1509,25 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         })
     });
 
-    let debugging_opts = build_debugging_options(matches, error_format);
+    let mut debugging_opts = build_debugging_options(matches, error_format);
+
+    if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
+        early_error(ErrorOutputType::Json(false),
+                    "--error-format=pretty-json is unstable");
+    }
 
     let mut output_types = BTreeMap::new();
     if !debugging_opts.parse_only {
         for list in matches.opt_strs("emit") {
             for output_type in list.split(',') {
                 let mut parts = output_type.splitn(2, '=');
-                let output_type = match parts.next().unwrap() {
-                    "asm" => OutputType::Assembly,
-                    "llvm-ir" => OutputType::LlvmAssembly,
-                    "mir" => OutputType::Mir,
-                    "llvm-bc" => OutputType::Bitcode,
-                    "obj" => OutputType::Object,
-                    "metadata" => OutputType::Metadata,
-                    "link" => OutputType::Exe,
-                    "dep-info" => OutputType::DepInfo,
-                    part => {
-                        early_error(error_format, &format!("unknown emission type: `{}`",
-                                                    part))
-                    }
+                let shorthand = parts.next().unwrap();
+                let output_type = match OutputType::from_shorthand(shorthand) {
+                    Some(output_type) => output_type,
+                    None => early_error(error_format, &format!(
+                        "unknown emission type: `{}` - expected one of: {}",
+                        shorthand, OutputType::shorthands_display(),
+                    )),
                 };
                 let path = parts.next().map(PathBuf::from);
                 output_types.insert(output_type, path);
@@ -1573,6 +1609,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         prints.push(PrintRequest::CodeModels);
         cg.code_model = None;
     }
+    if debugging_opts.tls_model.as_ref().map_or(false, |s| s == "help") {
+        prints.push(PrintRequest::TlsModels);
+        debugging_opts.tls_model = None;
+    }
 
     let cg = cg;
 
@@ -1672,6 +1712,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
             "target-features" => PrintRequest::TargetFeatures,
             "relocation-models" => PrintRequest::RelocationModels,
             "code-models" => PrintRequest::CodeModels,
+            "tls-models" => PrintRequest::TlsModels,
             "native-static-libs" => PrintRequest::NativeStaticLibs,
             "target-spec-json" => {
                 if nightly_options::is_unstable_enabled(matches) {
@@ -2254,46 +2295,46 @@ mod tests {
         let mut v5 = super::basic_options();
 
         // Reference
-        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Native changed
-        v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Crate changed
-        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Dependency changed
-        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Framework changed
-        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // All changed
-        v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json);
+        v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
 
         assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
@@ -2316,29 +2357,29 @@ mod tests {
         let mut v4 = super::basic_options();
 
         // Reference
-        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
+        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
 
         assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
@@ -2515,6 +2556,10 @@ mod tests {
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
         opts = reference.clone();
+        opts.debugging_opts.tls_model = Some(String::from("tls model"));
+        assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+        opts = reference.clone();
         opts.cg.metadata = vec![String::from("A"), String::from("B")];
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index be35cc8e4a1..39cf50787ef 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -24,7 +24,7 @@ use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
 
 use syntax::ast::NodeId;
-use errors::{self, DiagnosticBuilder};
+use errors::{self, DiagnosticBuilder, DiagnosticId};
 use errors::emitter::{Emitter, EmitterWriter};
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
@@ -187,7 +187,7 @@ impl Session {
     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                               sp: S,
                                                               msg: &str,
-                                                              code: &str)
+                                                              code: DiagnosticId)
                                                               -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
@@ -203,7 +203,7 @@ impl Session {
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
-                                                             code: &str)
+                                                             code: DiagnosticId)
                                                              -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
@@ -211,7 +211,11 @@ impl Session {
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_err(msg)
     }
-    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err_with_code<'a>(
+        &'a self,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_err_with_code(msg, code)
     }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
@@ -223,7 +227,7 @@ impl Session {
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
-                                                               code: &str)
+                                                               code: DiagnosticId)
                                                                -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
@@ -234,7 +238,12 @@ impl Session {
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         panic!(self.diagnostic().span_fatal(sp, msg))
     }
-    pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) -> ! {
+    pub fn span_fatal_with_code<S: Into<MultiSpan>>(
+        &self,
+        sp: S,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> ! {
         panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
     }
     pub fn fatal(&self, msg: &str) -> ! {
@@ -250,7 +259,7 @@ impl Session {
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_err(sp, msg)
     }
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.diagnostic().span_err_with_code(sp, &msg, code)
     }
     pub fn err(&self, msg: &str) {
@@ -283,7 +292,7 @@ impl Session {
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_warn(sp, msg)
     }
-    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.diagnostic().span_warn_with_code(sp, msg, code)
     }
     pub fn warn(&self, msg: &str) {
@@ -363,7 +372,7 @@ impl Session {
         match self.opts.error_format {
             // when outputting JSON for tool consumption, the tool might want
             // the duplicates
-            config::ErrorOutputType::Json => {
+            config::ErrorOutputType::Json(_) => {
                 do_method()
             },
             _ => {
@@ -727,11 +736,11 @@ pub fn build_session_with_codemap(sopts: config::Options,
         (config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
             Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false))
         }
-        (config::ErrorOutputType::Json, None) => {
-            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
+        (config::ErrorOutputType::Json(pretty), None) => {
+            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty))
         }
-        (config::ErrorOutputType::Json, Some(dst)) => {
-            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
+        (config::ErrorOutputType::Json(pretty), Some(dst)) => {
+            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty))
         }
         (config::ErrorOutputType::Short(color_config), None) => {
             Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true))
@@ -909,7 +918,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false))
         }
-        config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true))
         }
@@ -924,7 +933,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false))
         }
-        config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true))
         }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 1fddb186417..c08fe187f99 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -288,11 +288,11 @@ pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
 
-    /// Vtable for default trait implementations
+    /// Vtable for auto trait implementations
     /// This carries the information and nested obligations with regards
-    /// to a default implementation for a trait `Trait`. The nested obligations
+    /// to an auto implementation for a trait `Trait`. The nested obligations
     /// ensure the trait implementation holds for all the constituent types.
-    VtableDefaultImpl(VtableDefaultImplData<N>),
+    VtableAutoImpl(VtableAutoImplData<N>),
 
     /// Successful resolution to an obligation provided by the caller
     /// for some type parameter. The `Vec<N>` represents the
@@ -354,7 +354,7 @@ pub struct VtableClosureData<'tcx, N> {
 }
 
 #[derive(Clone)]
-pub struct VtableDefaultImplData<N> {
+pub struct VtableAutoImplData<N> {
     pub trait_def_id: DefId,
     pub nested: Vec<N>
 }
@@ -758,7 +758,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableImpl(i) => i.nested,
             VtableParam(n) => n,
             VtableBuiltin(i) => i.nested,
-            VtableDefaultImpl(d) => d.nested,
+            VtableAutoImpl(d) => d.nested,
             VtableClosure(c) => c.nested,
             VtableGenerator(c) => c.nested,
             VtableObject(d) => d.nested,
@@ -771,7 +771,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             &mut VtableImpl(ref mut i) => &mut i.nested,
             &mut VtableParam(ref mut n) => n,
             &mut VtableBuiltin(ref mut i) => &mut i.nested,
-            &mut VtableDefaultImpl(ref mut d) => &mut d.nested,
+            &mut VtableAutoImpl(ref mut d) => &mut d.nested,
             &mut VtableGenerator(ref mut c) => &mut c.nested,
             &mut VtableClosure(ref mut c) => &mut c.nested,
             &mut VtableObject(ref mut d) => &mut d.nested,
@@ -795,7 +795,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
                 vtable_base: o.vtable_base,
                 nested: o.nested.into_iter().map(f).collect(),
             }),
-            VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData {
+            VtableAutoImpl(d) => VtableAutoImpl(VtableAutoImplData {
                 trait_def_id: d.trait_def_id,
                 nested: d.nested.into_iter().map(f).collect(),
             }),
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 0fa1b32ceb7..9c56df058c3 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1116,7 +1116,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 // projection. And the projection where clause is handled
                 // in `assemble_candidates_from_param_env`.
             }
-            super::VtableDefaultImpl(..) |
+            super::VtableAutoImpl(..) |
             super::VtableBuiltin(..) => {
                 // These traits have no associated types.
                 span_bug!(
@@ -1182,7 +1182,7 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
             confirm_fn_pointer_candidate(selcx, obligation, data),
         super::VtableObject(_) =>
             confirm_object_candidate(selcx, obligation, obligation_trait_ref),
-        super::VtableDefaultImpl(..) |
+        super::VtableAutoImpl(..) |
         super::VtableParam(..) |
         super::VtableBuiltin(..) =>
             // we don't create Select candidates with this kind of resolution
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 6c573acf07d..7716770d318 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -25,9 +25,9 @@ use super::TraitNotObjectSafe;
 use super::Selection;
 use super::SelectionResult;
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableGenerator,
-            VtableFnPointer, VtableObject, VtableDefaultImpl};
+            VtableFnPointer, VtableObject, VtableAutoImpl};
 use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableGeneratorData,
-            VtableClosureData, VtableDefaultImplData, VtableFnPointerData};
+            VtableClosureData, VtableAutoImplData, VtableFnPointerData};
 use super::util;
 
 use dep_graph::{DepNodeIndex, DepKind};
@@ -225,7 +225,7 @@ enum SelectionCandidate<'tcx> {
     BuiltinCandidate { has_nested: bool },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(DefId),
-    DefaultImplCandidate(DefId),
+    AutoImplCandidate(DefId),
 
     /// This is a trait matching with a projected type as `Self`, and
     /// we found an applicable bound in the trait definition.
@@ -260,7 +260,7 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
                 }
             }
             ImplCandidate(def_id) => ImplCandidate(def_id),
-            DefaultImplCandidate(def_id) => DefaultImplCandidate(def_id),
+            AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
             ProjectionCandidate => ProjectionCandidate,
             FnPointerCandidate => FnPointerCandidate,
             ObjectCandidate => ObjectCandidate,
@@ -910,7 +910,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         let result = match predicate {
             ty::Predicate::Trait(ref data) => {
-                self.tcx().trait_has_default_impl(data.def_id())
+                self.tcx().trait_is_auto(data.def_id())
             }
             _ => {
                 false
@@ -1368,10 +1368,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
         self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-        // Default implementations have lower priority, so we only
+        // Auto implementations have lower priority, so we only
         // consider triggering a default if there is no other impl that can apply.
         if candidates.vec.is_empty() {
-            self.assemble_candidates_from_default_impls(obligation, &mut candidates)?;
+            self.assemble_candidates_from_auto_impls(obligation, &mut candidates)?;
         }
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
@@ -1686,18 +1686,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         Ok(())
     }
 
-    fn assemble_candidates_from_default_impls(&mut self,
+    fn assemble_candidates_from_auto_impls(&mut self,
                                               obligation: &TraitObligation<'tcx>,
                                               candidates: &mut SelectionCandidateSet<'tcx>)
                                               -> Result<(), SelectionError<'tcx>>
     {
         // OK to skip binder here because the tests we do below do not involve bound regions
         let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_from_default_impls(self_ty={:?})", self_ty);
+        debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
 
         let def_id = obligation.predicate.def_id();
 
-        if self.tcx().trait_has_default_impl(def_id) {
+        if self.tcx().trait_is_auto(def_id) {
             match self_ty.sty {
                 ty::TyDynamic(..) => {
                     // For object types, we don't know what the closed
@@ -1728,11 +1728,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     // this path.
                 }
                 ty::TyInfer(ty::TyVar(_)) => {
-                    // the defaulted impl might apply, we don't know
+                    // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
                 _ => {
-                    candidates.vec.push(DefaultImplCandidate(def_id.clone()))
+                    candidates.vec.push(AutoImplCandidate(def_id.clone()))
                 }
             }
         }
@@ -1933,7 +1933,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         match other.candidate {
             ObjectCandidate |
             ParamCandidate(_) | ProjectionCandidate => match victim.candidate {
-                DefaultImplCandidate(..) => {
+                AutoImplCandidate(..) => {
                     bug!(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
@@ -2282,9 +2282,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 Ok(VtableParam(obligations))
             }
 
-            DefaultImplCandidate(trait_def_id) => {
-                let data = self.confirm_default_impl_candidate(obligation, trait_def_id);
-                Ok(VtableDefaultImpl(data))
+            AutoImplCandidate(trait_def_id) => {
+                let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
+                Ok(VtableAutoImpl(data))
             }
 
             ImplCandidate(impl_def_id) => {
@@ -2417,29 +2417,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     ///
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
     /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
-    fn confirm_default_impl_candidate(&mut self,
+    fn confirm_auto_impl_candidate(&mut self,
                                       obligation: &TraitObligation<'tcx>,
                                       trait_def_id: DefId)
-                                      -> VtableDefaultImplData<PredicateObligation<'tcx>>
+                                      -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
-        debug!("confirm_default_impl_candidate({:?}, {:?})",
+        debug!("confirm_auto_impl_candidate({:?}, {:?})",
                obligation,
                trait_def_id);
 
         // binder is moved below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
         let types = self.constituent_types_for_ty(self_ty);
-        self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types))
+        self.vtable_auto_impl(obligation, trait_def_id, ty::Binder(types))
     }
 
-    /// See `confirm_default_impl_candidate`
-    fn vtable_default_impl(&mut self,
+    /// See `confirm_auto_impl_candidate`
+    fn vtable_auto_impl(&mut self,
                            obligation: &TraitObligation<'tcx>,
                            trait_def_id: DefId,
                            nested: ty::Binder<Vec<Ty<'tcx>>>)
-                           -> VtableDefaultImplData<PredicateObligation<'tcx>>
+                           -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
-        debug!("vtable_default_impl: nested={:?}", nested);
+        debug!("vtable_auto_impl: nested={:?}", nested);
 
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
         let mut obligations = self.collect_predicates_for_types(
@@ -2465,9 +2465,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         obligations.extend(trait_obligations);
 
-        debug!("vtable_default_impl: obligations={:?}", obligations);
+        debug!("vtable_auto_impl: obligations={:?}", obligations);
 
-        VtableDefaultImplData {
+        VtableAutoImplData {
             trait_def_id,
             nested: obligations
         }
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 19ed03aa149..fd93aa162a6 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -47,7 +47,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::Vtable<'tcx, N> {
             super::VtableImpl(ref v) =>
                 write!(f, "{:?}", v),
 
-            super::VtableDefaultImpl(ref t) =>
+            super::VtableAutoImpl(ref t) =>
                 write!(f, "{:?}", t),
 
             super::VtableClosure(ref d) =>
@@ -104,9 +104,9 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableBuiltinData<N> {
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableDefaultImplData<N> {
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableDefaultImplData(trait_def_id={:?}, nested={:?})",
+        write!(f, "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
                self.trait_def_id,
                self.nested)
     }
@@ -292,7 +292,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
                     })
                 })
             }
-            traits::VtableDefaultImpl(t) => Some(traits::VtableDefaultImpl(t)),
+            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
             traits::VtableGenerator(traits::VtableGeneratorData {
                 closure_def_id,
                 substs,
@@ -407,9 +407,9 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureDa
     }
 }
 
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableAutoImplData<N> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        traits::VtableDefaultImplData {
+        traits::VtableAutoImplData {
             trait_def_id: self.trait_def_id,
             nested: self.nested.fold_with(folder),
         }
@@ -463,7 +463,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
             traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
-            traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
+            traits::VtableAutoImpl(ref t) => traits::VtableAutoImpl(t.fold_with(folder)),
             traits::VtableGenerator(ref d) => {
                 traits::VtableGenerator(d.fold_with(folder))
             }
@@ -482,7 +482,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             traits::VtableImpl(ref v) => v.visit_with(visitor),
-            traits::VtableDefaultImpl(ref t) => t.visit_with(visitor),
+            traits::VtableAutoImpl(ref t) => t.visit_with(visitor),
             traits::VtableGenerator(ref d) => d.visit_with(visitor),
             traits::VtableClosure(ref d) => d.visit_with(visitor),
             traits::VtableFnPointer(ref d) => d.visit_with(visitor),
diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs
index 761e7259204..73fdbfe8831 100644
--- a/src/librustc/traits/trans/mod.rs
+++ b/src/librustc/traits/trans/mod.rs
@@ -99,6 +99,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         let substituted = self.erase_regions(&substituted);
         AssociatedTypeNormalizer::new(self).fold(&substituted)
     }
+
+    pub fn trans_apply_param_substs_env<T>(
+        self,
+        param_substs: &Substs<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> T
+    where
+        T: TransNormalize<'tcx>,
+    {
+        debug!(
+            "apply_param_substs_env(param_substs={:?}, value={:?}, param_env={:?})",
+            param_substs,
+            value,
+            param_env,
+        );
+        let substituted = value.subst(self, param_substs);
+        let substituted = self.erase_regions(&substituted);
+        AssociatedTypeNormalizerEnv::new(self, param_env).fold(&substituted)
+    }
 }
 
 struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
@@ -134,6 +154,40 @@ impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
     }
 }
 
+struct AssociatedTypeNormalizerEnv<'a, 'gcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    param_env: ty::ParamEnv<'gcx>,
+}
+
+impl<'a, 'gcx> AssociatedTypeNormalizerEnv<'a, 'gcx> {
+    fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>, param_env: ty::ParamEnv<'gcx>) -> Self {
+        Self { tcx, param_env }
+    }
+
+    fn fold<T: TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
+        if !value.has_projections() {
+            value.clone()
+        } else {
+            value.fold_with(self)
+        }
+    }
+}
+
+impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizerEnv<'a, 'gcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
+        if !ty.has_projections() {
+            ty
+        } else {
+            debug!("AssociatedTypeNormalizerEnv: ty={:?}", ty);
+            self.tcx.normalize_associated_type_in_env(&ty, self.param_env)
+        }
+    }
+}
+
 // Implement DepTrackingMapConfig for `trait_cache`
 pub struct TraitSelectionCache<'tcx> {
     data: PhantomData<&'tcx ()>
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
new file mode 100644
index 00000000000..1c793920bf2
--- /dev/null
+++ b/src/librustc/ty/codec.rs
@@ -0,0 +1,243 @@
+// 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.
+
+// This module contains some shared code for encoding and decoding various
+// things from the `ty` module, and in particular implements support for
+// "shorthands" which allow to have pointers back into the already encoded
+// stream instead of re-encoding the same thing twice.
+//
+// The functionality in here is shared between persisting to crate metadata and
+// persisting to incr. comp. caches.
+
+use hir::def_id::{DefId, CrateNum};
+use middle::const_val::ByteArray;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_serialize::{Decodable, Decoder, Encoder, Encodable};
+use std::hash::Hash;
+use std::intrinsics;
+use ty::{self, Ty, TyCtxt};
+use ty::subst::Substs;
+
+/// The shorthand encoding uses an enum's variant index `usize`
+/// and is offset by this value so it never matches a real variant.
+/// This offset is also chosen so that the first byte is never < 0x80.
+pub const SHORTHAND_OFFSET: usize = 0x80;
+
+pub trait EncodableWithShorthand: Clone + Eq + Hash {
+    type Variant: Encodable;
+    fn variant(&self) -> &Self::Variant;
+}
+
+impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
+    type Variant = ty::TypeVariants<'tcx>;
+    fn variant(&self) -> &Self::Variant {
+        &self.sty
+    }
+}
+
+impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
+    type Variant = ty::Predicate<'tcx>;
+    fn variant(&self) -> &Self::Variant {
+        self
+    }
+}
+
+pub trait TyEncoder: Encoder {
+    fn position(&self) -> usize;
+}
+
+/// Encode the given value or a previously cached shorthand.
+pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
+                                      value: &T,
+                                      cache: M)
+                                      -> Result<(), E::Error>
+    where E: TyEncoder,
+          M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
+          T: EncodableWithShorthand,
+{
+    let existing_shorthand = cache(encoder).get(value).cloned();
+    if let Some(shorthand) = existing_shorthand {
+        return encoder.emit_usize(shorthand);
+    }
+
+    let variant = value.variant();
+
+    let start = encoder.position();
+    variant.encode(encoder)?;
+    let len = encoder.position() - start;
+
+    // The shorthand encoding uses the same usize as the
+    // discriminant, with an offset so they can't conflict.
+    let discriminant = unsafe { intrinsics::discriminant_value(variant) };
+    assert!(discriminant < SHORTHAND_OFFSET as u64);
+    let shorthand = start + SHORTHAND_OFFSET;
+
+    // Get the number of bits that leb128 could fit
+    // in the same space as the fully encoded type.
+    let leb128_bits = len * 7;
+
+    // Check that the shorthand is a not longer than the
+    // full encoding itself, i.e. it's an obvious win.
+    if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
+        cache(encoder).insert(value.clone(), shorthand);
+    }
+
+    Ok(())
+}
+
+pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
+                                     predicates: &ty::GenericPredicates<'tcx>,
+                                     cache: C)
+                                     -> Result<(), E::Error>
+    where E: TyEncoder,
+          C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
+{
+    predicates.parent.encode(encoder)?;
+    predicates.predicates.len().encode(encoder)?;
+    for predicate in &predicates.predicates {
+        encode_with_shorthand(encoder, predicate, &cache)?
+    }
+    Ok(())
+}
+
+pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
+
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
+
+    fn peek_byte(&self) -> u8;
+
+    fn cached_ty_for_shorthand<F>(&mut self,
+                                  shorthand: usize,
+                                  or_insert_with: F)
+                                  -> Result<Ty<'tcx>, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
+
+    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
+        where F: FnOnce(&mut Self) -> R;
+
+    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
+
+    fn positioned_at_shorthand(&self) -> bool {
+        (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
+    }
+}
+
+pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    let cnum = CrateNum::from_u32(u32::decode(decoder)?);
+    Ok(decoder.map_encoded_cnum_to_current(cnum))
+}
+
+pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    // Handle shorthands first, if we have an usize > 0x80.
+    // if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
+    if decoder.positioned_at_shorthand() {
+        let pos = decoder.read_usize()?;
+        assert!(pos >= SHORTHAND_OFFSET);
+        let shorthand = pos - SHORTHAND_OFFSET;
+
+        decoder.cached_ty_for_shorthand(shorthand, |decoder| {
+            decoder.with_position(shorthand, Ty::decode)
+        })
+    } else {
+        let tcx = decoder.tcx();
+        Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?))
+    }
+}
+
+pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
+                                      -> Result<ty::GenericPredicates<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(ty::GenericPredicates {
+        parent: Decodable::decode(decoder)?,
+        predicates: (0..decoder.read_usize()?).map(|_| {
+                // Handle shorthands first, if we have an usize > 0x80.
+                if decoder.positioned_at_shorthand() {
+                    let pos = decoder.read_usize()?;
+                    assert!(pos >= SHORTHAND_OFFSET);
+                    let shorthand = pos - SHORTHAND_OFFSET;
+
+                    decoder.with_position(shorthand, ty::Predicate::decode)
+                } else {
+                    ty::Predicate::decode(decoder)
+                }
+            })
+            .collect::<Result<Vec<_>, _>>()?,
+    })
+}
+
+pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    let len = decoder.read_usize()?;
+    let tcx = decoder.tcx();
+    Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
+}
+
+pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
+}
+
+pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
+                                    -> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    let len = decoder.read_usize()?;
+    Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
+}
+
+pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
+                                   -> Result<&'tcx ty::AdtDef, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    let def_id = DefId::decode(decoder)?;
+    Ok(decoder.tcx().adt_def(def_id))
+}
+
+pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
+    -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    let len = decoder.read_usize()?;
+    Ok(decoder.tcx()
+              .mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
+}
+
+pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
+                                      -> Result<ByteArray<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(ByteArray {
+        data: decoder.tcx().alloc_byte_array(&Vec::decode(decoder)?)
+    })
+}
+
+pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
+                                 -> Result<&'tcx ty::Const<'tcx>, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
+}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6ab81a41d68..37c4346a7dc 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -855,6 +855,11 @@ pub struct GlobalCtxt<'tcx> {
 
     pub dep_graph: DepGraph,
 
+    /// This provides access to the incr. comp. on-disk cache for query results.
+    /// Do not access this directly. It is only meant to be used by
+    /// `DepGraph::try_mark_green()` and the query infrastructure in `ty::maps`.
+    pub(crate) on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
+
     /// Common types, pre-interned for your convenience.
     pub types: CommonTypes<'tcx>,
 
@@ -1056,6 +1061,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   resolutions: ty::Resolutions,
                                   named_region_map: resolve_lifetime::NamedRegionMap,
                                   hir: hir_map::Map<'tcx>,
+                                  on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
                                   crate_name: &str,
                                   tx: mpsc::Sender<Box<Any + Send>>,
                                   output_filenames: &OutputFilenames,
@@ -1139,6 +1145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             global_arenas: arenas,
             global_interners: interners,
             dep_graph: dep_graph.clone(),
+            on_disk_query_result_cache,
             types: common_types,
             named_region_map: NamedRegionMap {
                 defs,
@@ -1300,6 +1307,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             self.in_scope_traits_map(def_index);
         }
     }
+
+    pub fn serialize_query_result_cache<E>(self,
+                                           encoder: &mut E)
+                                           -> Result<(), E::Error>
+        where E: ::rustc_serialize::Encoder
+    {
+        self.on_disk_query_result_cache.serialize(encoder)
+    }
+
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index edd4329fa41..149999e0eee 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -218,6 +218,43 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     {
         value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
     }
+
+    pub fn for_each_free_region<T,F>(self,
+                                     value: &T,
+                                     callback: F)
+        where F: FnMut(ty::Region<'tcx>),
+              T: TypeFoldable<'tcx>,
+    {
+        value.visit_with(&mut RegionVisitor { current_depth: 0, callback });
+
+        struct RegionVisitor<F> {
+            current_depth: u32,
+            callback: F,
+        }
+
+        impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
+            where F : FnMut(ty::Region<'tcx>)
+        {
+            fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
+                self.current_depth += 1;
+                t.skip_binder().visit_with(self);
+                self.current_depth -= 1;
+
+                false // keep visiting
+            }
+
+            fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+                match *r {
+                    ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
+                        /* ignore bound regions */
+                    }
+                    _ => (self.callback)(r),
+                }
+
+                false // keep visiting
+            }
+        }
+    }
 }
 
 /// Folds over the substructure of a type, visiting its component
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 442c79393fd..6ea953c3f73 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> Instance<'tcx> {
             resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
         } else {
             let ty = tcx.type_of(def_id);
-            let item_type = tcx.trans_apply_param_substs(substs, &ty);
+            let item_type = tcx.trans_apply_param_substs_env(substs, param_env, &ty);
 
             let def = match item_type.sty {
                 ty::TyFnDef(..) if {
@@ -256,7 +256,7 @@ fn resolve_associated_item<'a, 'tcx>(
                 None
             }
         }
-        traits::VtableDefaultImpl(..) | traits::VtableParam(..) => None
+        traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
     }
 }
 
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 98c55331f8a..24c19bfc3f3 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         // Always use types for non-local impls, where types are always
         // available, and filename/line-number is mostly uninteresting.
-        let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
+        let use_types = !self.is_auto_impl(impl_def_id) && (!impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
             !force_no_types
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 79fee8bf930..7d8586741fb 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -70,6 +70,9 @@ mod config;
 pub use self::config::QueryConfig;
 use self::config::QueryDescription;
 
+mod on_disk_cache;
+pub use self::on_disk_cache::OnDiskCache;
+
 // Each of these maps also corresponds to a method on a
 // `Provider` trait for requesting a value of that type,
 // and a method on `Maps` itself for doing that in a
@@ -110,8 +113,8 @@ define_maps! { <'tcx>
     /// True if this is a foreign item (i.e., linked via `extern { ... }`).
     [] fn is_foreign_item: IsForeignItem(DefId) -> bool,
 
-    /// True if this is a default impl (aka impl Foo for ..)
-    [] fn is_default_impl: IsDefaultImpl(DefId) -> bool,
+    /// True if this is an auto impl (aka impl Foo for ..)
+    [] fn is_auto_impl: IsAutoImpl(DefId) -> bool,
 
     /// Get a map with the variance of every item; use `item_variance`
     /// instead.
diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs
new file mode 100644
index 00000000000..26581501234
--- /dev/null
+++ b/src/librustc/ty/maps/on_disk_cache.rs
@@ -0,0 +1,231 @@
+// 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.
+
+use dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::indexed_vec::Idx;
+use errors::Diagnostic;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
+                      SpecializedDecoder};
+use session::Session;
+use std::borrow::Cow;
+use std::cell::RefCell;
+use std::collections::BTreeMap;
+use std::mem;
+use syntax::codemap::{CodeMap, StableFilemapId};
+use syntax_pos::{BytePos, Span, NO_EXPANSION, DUMMY_SP};
+
+/// `OnDiskCache` provides an interface to incr. comp. data cached from the
+/// previous compilation session. This data will eventually include the results
+/// of a few selected queries (like `typeck_tables_of` and `mir_optimized`) and
+/// any diagnostics that have been emitted during a query.
+pub struct OnDiskCache<'sess> {
+    // The diagnostics emitted during the previous compilation session.
+    prev_diagnostics: FxHashMap<SerializedDepNodeIndex, Vec<Diagnostic>>,
+
+    // This field collects all Diagnostics emitted during the current
+    // compilation session.
+    current_diagnostics: RefCell<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
+
+    // This will eventually be needed for creating Decoders that can rebase
+    // spans.
+    _prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
+    codemap: &'sess CodeMap,
+}
+
+// This type is used only for (de-)serialization.
+#[derive(RustcEncodable, RustcDecodable)]
+struct Header {
+    prev_filemap_starts: BTreeMap<BytePos, StableFilemapId>,
+}
+
+// This type is used only for (de-)serialization.
+#[derive(RustcEncodable, RustcDecodable)]
+struct Body {
+    diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)>,
+}
+
+impl<'sess> OnDiskCache<'sess> {
+    /// Create a new OnDiskCache instance from the serialized data in `data`.
+    /// Note that the current implementation (which only deals with diagnostics
+    /// so far) will eagerly deserialize the complete cache. Once we are
+    /// dealing with larger amounts of data (i.e. cached query results),
+    /// deserialization will need to happen lazily.
+    pub fn new(sess: &'sess Session, data: &[u8]) -> OnDiskCache<'sess> {
+        debug_assert!(sess.opts.incremental.is_some());
+
+        let mut decoder = opaque::Decoder::new(&data[..], 0);
+        let header = Header::decode(&mut decoder).unwrap();
+
+        let prev_diagnostics: FxHashMap<_, _> = {
+            let mut decoder = CacheDecoder {
+                opaque: decoder,
+                codemap: sess.codemap(),
+                prev_filemap_starts: &header.prev_filemap_starts,
+            };
+            let body = Body::decode(&mut decoder).unwrap();
+            body.diagnostics.into_iter().collect()
+        };
+
+        OnDiskCache {
+            prev_diagnostics,
+            _prev_filemap_starts: header.prev_filemap_starts,
+            codemap: sess.codemap(),
+            current_diagnostics: RefCell::new(FxHashMap()),
+        }
+    }
+
+    pub fn new_empty(codemap: &'sess CodeMap) -> OnDiskCache<'sess> {
+        OnDiskCache {
+            prev_diagnostics: FxHashMap(),
+            _prev_filemap_starts: BTreeMap::new(),
+            codemap,
+            current_diagnostics: RefCell::new(FxHashMap()),
+        }
+    }
+
+    pub fn serialize<'a, 'tcx, E>(&self,
+                                  encoder: &mut E)
+                                  -> Result<(), E::Error>
+        where E: Encoder
+    {
+        let prev_filemap_starts: BTreeMap<_, _> = self
+            .codemap
+            .files()
+            .iter()
+            .map(|fm| (fm.start_pos, StableFilemapId::new(fm)))
+            .collect();
+
+        Header { prev_filemap_starts }.encode(encoder)?;
+
+        let diagnostics: Vec<(SerializedDepNodeIndex, Vec<Diagnostic>)> =
+            self.current_diagnostics
+                .borrow()
+                .iter()
+                .map(|(k, v)| (SerializedDepNodeIndex::new(k.index()), v.clone()))
+                .collect();
+
+        Body { diagnostics }.encode(encoder)?;
+
+        Ok(())
+    }
+
+    /// Load a diagnostic emitted during the previous compilation session.
+    pub fn load_diagnostics(&self,
+                            dep_node_index: SerializedDepNodeIndex)
+                            -> Vec<Diagnostic> {
+        self.prev_diagnostics.get(&dep_node_index).cloned().unwrap_or(vec![])
+    }
+
+    /// Store a diagnostic emitted during the current compilation session.
+    /// Anything stored like this will be available via `load_diagnostics` in
+    /// the next compilation session.
+    pub fn store_diagnostics(&self,
+                             dep_node_index: DepNodeIndex,
+                             diagnostics: Vec<Diagnostic>) {
+        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
+        let prev = current_diagnostics.insert(dep_node_index, diagnostics);
+        debug_assert!(prev.is_none());
+    }
+
+    /// Store a diagnostic emitted during computation of an anonymous query.
+    /// Since many anonymous queries can share the same `DepNode`, we aggregate
+    /// them -- as opposed to regular queries where we assume that there is a
+    /// 1:1 relationship between query-key and `DepNode`.
+    pub fn store_diagnostics_for_anon_node(&self,
+                                           dep_node_index: DepNodeIndex,
+                                           mut diagnostics: Vec<Diagnostic>) {
+        let mut current_diagnostics = self.current_diagnostics.borrow_mut();
+
+        let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
+            mem::replace(&mut diagnostics, Vec::new())
+        });
+
+        x.extend(diagnostics.into_iter());
+    }
+}
+
+/// A decoder that can read the incr. comp. cache. It is similar to the one
+/// we use for crate metadata decoding in that it can rebase spans and
+/// eventually will also handle things that contain `Ty` instances.
+struct CacheDecoder<'a> {
+    opaque: opaque::Decoder<'a>,
+    codemap: &'a CodeMap,
+    prev_filemap_starts: &'a BTreeMap<BytePos, StableFilemapId>,
+}
+
+impl<'a> CacheDecoder<'a> {
+    fn find_filemap_prev_bytepos(&self,
+                                 prev_bytepos: BytePos)
+                                 -> Option<(BytePos, StableFilemapId)> {
+        for (start, id) in self.prev_filemap_starts.range(BytePos(0) ... prev_bytepos).rev() {
+            return Some((*start, *id))
+        }
+
+        None
+    }
+}
+
+macro_rules! decoder_methods {
+    ($($name:ident -> $ty:ty;)*) => {
+        $(fn $name(&mut self) -> Result<$ty, Self::Error> {
+            self.opaque.$name()
+        })*
+    }
+}
+
+impl<'sess> Decoder for CacheDecoder<'sess> {
+    type Error = String;
+
+    decoder_methods! {
+        read_nil -> ();
+
+        read_u128 -> u128;
+        read_u64 -> u64;
+        read_u32 -> u32;
+        read_u16 -> u16;
+        read_u8 -> u8;
+        read_usize -> usize;
+
+        read_i128 -> i128;
+        read_i64 -> i64;
+        read_i32 -> i32;
+        read_i16 -> i16;
+        read_i8 -> i8;
+        read_isize -> isize;
+
+        read_bool -> bool;
+        read_f64 -> f64;
+        read_f32 -> f32;
+        read_char -> char;
+        read_str -> Cow<str>;
+    }
+
+    fn error(&mut self, err: &str) -> Self::Error {
+        self.opaque.error(err)
+    }
+}
+
+impl<'a> SpecializedDecoder<Span> for CacheDecoder<'a> {
+    fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
+        let lo = BytePos::decode(self)?;
+        let hi = BytePos::decode(self)?;
+
+        if let Some((prev_filemap_start, filemap_id)) = self.find_filemap_prev_bytepos(lo) {
+            if let Some(current_filemap) = self.codemap.filemap_by_stable_id(filemap_id) {
+                let lo = (lo + current_filemap.start_pos) - prev_filemap_start;
+                let hi = (hi + current_filemap.start_pos) - prev_filemap_start;
+                return Ok(Span::new(lo, hi, NO_EXPANSION));
+            }
+        }
+
+        Ok(DUMMY_SP)
+    }
+}
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index bb042be5254..24148bcc83f 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -13,14 +13,14 @@
 //! provider, manage the caches, and so forth.
 
 use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
-use errors::{Diagnostic, DiagnosticBuilder};
+use errors::DiagnosticBuilder;
 use ty::{TyCtxt};
 use ty::maps::Query; // NB: actually generated by the macros in this file
 use ty::maps::config::QueryDescription;
 use ty::item_path;
 
 use rustc_data_structures::fx::{FxHashMap};
-use std::cell::{RefMut, Cell};
+use std::cell::RefMut;
 use std::marker::PhantomData;
 use std::mem;
 use syntax_pos::Span;
@@ -33,34 +33,19 @@ pub(super) struct QueryMap<D: QueryDescription> {
 pub(super) struct QueryValue<T> {
     pub(super) value: T,
     pub(super) index: DepNodeIndex,
-    pub(super) diagnostics: Option<Box<QueryDiagnostics>>,
 }
 
 impl<T> QueryValue<T> {
     pub(super) fn new(value: T,
-                      dep_node_index: DepNodeIndex,
-                      diagnostics: Vec<Diagnostic>)
+                      dep_node_index: DepNodeIndex)
                       -> QueryValue<T> {
         QueryValue {
             value,
             index: dep_node_index,
-            diagnostics: if diagnostics.len() == 0 {
-                None
-            } else {
-                Some(Box::new(QueryDiagnostics {
-                    diagnostics,
-                    emitted_diagnostics: Cell::new(true),
-                }))
-            },
         }
     }
 }
 
-pub(super) struct QueryDiagnostics {
-    pub(super) diagnostics: Vec<Diagnostic>,
-    pub(super) emitted_diagnostics: Cell<bool>,
-}
-
 impl<M: QueryDescription> QueryMap<M> {
     pub(super) fn new() -> QueryMap<M> {
         QueryMap {
@@ -284,16 +269,6 @@ macro_rules! define_maps {
                 );
 
                 if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
-                    if let Some(ref d) = value.diagnostics {
-                        if !d.emitted_diagnostics.get() {
-                            d.emitted_diagnostics.set(true);
-                            let handle = tcx.sess.diagnostic();
-                            for diagnostic in d.diagnostics.iter() {
-                                DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone())
-                                    .emit();
-                            }
-                        }
-                    }
                     profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
                     tcx.dep_graph.read_index(value.index);
                     return Ok((&value.value).clone());
@@ -331,7 +306,11 @@ macro_rules! define_maps {
                     let ((result, dep_node_index), diagnostics) = res;
 
                     tcx.dep_graph.read_index(dep_node_index);
-                    let value = QueryValue::new(result, dep_node_index, diagnostics);
+
+                    tcx.on_disk_query_result_cache
+                       .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
+
+                    let value = QueryValue::new(result, dep_node_index);
 
                     return Ok((&tcx.maps
                                     .$name
@@ -348,7 +327,8 @@ macro_rules! define_maps {
                         return Self::load_from_disk_and_cache_in_memory(tcx,
                                                                         key,
                                                                         span,
-                                                                        dep_node_index)
+                                                                        dep_node_index,
+                                                                        &dep_node)
                     }
                 }
 
@@ -393,13 +373,17 @@ macro_rules! define_maps {
             fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>,
                                                   key: $K,
                                                   span: Span,
-                                                  dep_node_index: DepNodeIndex)
+                                                  dep_node_index: DepNodeIndex,
+                                                  dep_node: &DepNode)
                                                   -> Result<$V, CycleError<'a, $tcx>>
             {
                 debug_assert!(tcx.dep_graph.is_green(dep_node_index));
 
-                // We don't do any caching yet, so recompute
-                let (result, diagnostics) = tcx.cycle_check(span, Query::$name(key), || {
+                // We don't do any caching yet, so recompute.
+                // The diagnostics for this query have already been promoted to
+                // the current session during try_mark_green(), so we can ignore
+                // them here.
+                let (result, _) = tcx.cycle_check(span, Query::$name(key), || {
                     tcx.sess.diagnostic().track_diagnostics(|| {
                         // The dep-graph for this computation is already in place
                         tcx.dep_graph.with_ignore(|| {
@@ -408,11 +392,37 @@ macro_rules! define_maps {
                     })
                 })?;
 
+                // If -Zincremental-verify-ich is specified, re-hash results from
+                // the cache and make sure that they have the expected fingerprint.
+                if tcx.sess.opts.debugging_opts.incremental_verify_ich {
+                    use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
+                    use ich::Fingerprint;
+
+                    assert!(Some(tcx.dep_graph.fingerprint_of(dep_node)) ==
+                            tcx.dep_graph.prev_fingerprint_of(dep_node),
+                            "Fingerprint for green query instance not loaded \
+                             from cache: {:?}", dep_node);
+
+                    debug!("BEGIN verify_ich({:?})", dep_node);
+                    let mut hcx = tcx.create_stable_hashing_context();
+                    let mut hasher = StableHasher::new();
+
+                    result.hash_stable(&mut hcx, &mut hasher);
+
+                    let new_hash: Fingerprint = hasher.finish();
+                    debug!("END verify_ich({:?})", dep_node);
+
+                    let old_hash = tcx.dep_graph.fingerprint_of(dep_node);
+
+                    assert!(new_hash == old_hash, "Found unstable fingerprints \
+                        for {:?}", dep_node);
+                }
+
                 if tcx.sess.opts.debugging_opts.query_dep_graph {
                     tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true);
                 }
 
-                let value = QueryValue::new(result, dep_node_index, diagnostics);
+                let value = QueryValue::new(result, dep_node_index);
 
                 Ok((&tcx.maps
                          .$name
@@ -454,7 +464,12 @@ macro_rules! define_maps {
                     tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false);
                 }
 
-                let value = QueryValue::new(result, dep_node_index, diagnostics);
+                if dep_node.kind != ::dep_graph::DepKind::Null {
+                    tcx.on_disk_query_result_cache
+                       .store_diagnostics(dep_node_index, diagnostics);
+                }
+
+                let value = QueryValue::new(result, dep_node_index);
 
                 Ok(((&tcx.maps
                          .$name
@@ -706,9 +721,8 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::EraseRegionsTy |
         DepKind::NormalizeTy |
 
-        // These are just odd
-        DepKind::Null |
-        DepKind::WorkProduct => {
+        // This one should never occur in this context
+        DepKind::Null => {
             bug!("force_from_dep_node() - Encountered {:?}", dep_node.kind)
         }
 
@@ -744,7 +758,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
         DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
-        DepKind::IsDefaultImpl => { force!(is_default_impl, def_id!()); }
+        DepKind::IsAutoImpl => { force!(is_auto_impl, def_id!()); }
         DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
         DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
         DepKind::ClosureKind => { force!(closure_kind, def_id!()); }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b3f2886cdf9..0deababd218 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -89,6 +89,7 @@ pub use self::maps::queries;
 pub mod adjustment;
 pub mod binding;
 pub mod cast;
+pub mod codec;
 pub mod error;
 mod erase_regions;
 pub mod fast_reject;
@@ -1325,6 +1326,12 @@ bitflags! {
         const IS_FUNDAMENTAL      = 1 << 2;
         const IS_UNION            = 1 << 3;
         const IS_BOX              = 1 << 4;
+        /// Indicates whether this abstract data type will be expanded on in future (new
+        /// fields/variants) and as such, whether downstream crates must match exhaustively on the
+        /// fields/variants of this data type.
+        ///
+        /// See RFC 2008 (https://github.com/rust-lang/rfcs/pull/2008).
+        const IS_NON_EXHAUSTIVE   = 1 << 5;
     }
 }
 
@@ -1525,6 +1532,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
+        if tcx.has_attr(did, "non_exhaustive") {
+            flags = flags | AdtFlags::IS_NON_EXHAUSTIVE;
+        }
         match kind {
             AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
             AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
@@ -1553,6 +1563,11 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         self.flags.intersects(AdtFlags::IS_ENUM)
     }
 
+    #[inline]
+    pub fn is_non_exhaustive(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE)
+    }
+
     /// Returns the kind of the ADT - Struct or Enum.
     #[inline]
     pub fn adt_kind(&self) -> AdtKind {
@@ -2307,8 +2322,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.get_attrs(did).iter().any(|item| item.check_name(attr))
     }
 
-    pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
-        self.trait_def(trait_def_id).has_default_impl
+    /// Returns true if this is an `auto trait`.
+    ///
+    /// NB. For a limited time, also returns true if `impl Trait for .. { }` is in the code-base.
+    pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
+        self.trait_def(trait_def_id).has_auto_impl
     }
 
     pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> {
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index e0b05c2ba39..0fbf9f1bd58 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -34,7 +34,7 @@ pub struct TraitDef {
     /// be usable with the sugar (or without it).
     pub paren_sugar: bool,
 
-    pub has_default_impl: bool,
+    pub has_auto_impl: bool,
 
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
@@ -51,14 +51,14 @@ impl<'a, 'gcx, 'tcx> TraitDef {
     pub fn new(def_id: DefId,
                unsafety: hir::Unsafety,
                paren_sugar: bool,
-               has_default_impl: bool,
+               has_auto_impl: bool,
                def_path_hash: DefPathHash)
                -> TraitDef {
         TraitDef {
             def_id,
             paren_sugar,
             unsafety,
-            has_default_impl,
+            has_auto_impl,
             def_path_hash,
         }
     }
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index eafb4c5c800..352184c1efa 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -177,9 +177,13 @@ impl<'a> AllocFnFactory<'a> {
 
         let no_mangle = Symbol::intern("no_mangle");
         let no_mangle = self.cx.meta_word(self.span, no_mangle);
+
+        let special = Symbol::intern("rustc_std_internal_symbol");
+        let special = self.cx.meta_word(self.span, special);
         vec![
             self.cx.attribute(self.span, linkage),
             self.cx.attribute(self.span, no_mangle),
+            self.cx.attribute(self.span, special),
         ]
     }
 
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index 9e348f62223..09c9cecdcee 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -96,7 +96,7 @@ impl Status {
 }
 
 impl<T> StatusAnd<T> {
-    fn map<F: FnOnce(T) -> U, U>(self, f: F) -> StatusAnd<U> {
+    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> StatusAnd<U> {
         StatusAnd {
             status: self.status,
             value: f(self.value),
@@ -378,7 +378,7 @@ pub trait Float
     fn from_bits(input: u128) -> Self;
     fn from_i128_r(input: i128, round: Round) -> StatusAnd<Self> {
         if input < 0 {
-            Self::from_u128_r(-input as u128, -round).map(|r| -r)
+            Self::from_u128_r(input.wrapping_neg() as u128, -round).map(|r| -r)
         } else {
             Self::from_u128_r(input as u128, round)
         }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index a56d0678158..8fd4aad89c6 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -311,6 +311,9 @@ pub struct TargetOptions {
     pub relocation_model: String,
     /// Code model to use. Corresponds to `llc -code-model=$code_model`. Defaults to "default".
     pub code_model: String,
+    /// TLS model to use. Options are "global-dynamic" (default), "local-dynamic", "initial-exec"
+    /// and "local-exec". This is similar to the -ftls-model option in GCC/Clang.
+    pub tls_model: String,
     /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
     pub disable_redzone: bool,
     /// Eliminate frame pointers from stack frames if possible. Defaults to true.
@@ -450,6 +453,7 @@ impl Default for TargetOptions {
             executables: false,
             relocation_model: "pic".to_string(),
             code_model: "default".to_string(),
+            tls_model: "global-dynamic".to_string(),
             disable_redzone: false,
             eliminate_frame_pointer: true,
             function_sections: true,
@@ -696,6 +700,7 @@ impl Target {
         key!(executables, bool);
         key!(relocation_model);
         key!(code_model);
+        key!(tls_model);
         key!(disable_redzone, bool);
         key!(eliminate_frame_pointer, bool);
         key!(function_sections, bool);
@@ -888,6 +893,7 @@ impl ToJson for Target {
         target_option_val!(executables);
         target_option_val!(relocation_model);
         target_option_val!(code_model);
+        target_option_val!(tls_model);
         target_option_val!(disable_redzone);
         target_option_val!(eliminate_frame_pointer);
         target_option_val!(function_sections);
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index c1d0d849dfb..908737669c5 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -484,7 +484,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             // 3. Where does old loan expire.
 
             let previous_end_span =
-                old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree).end_point();
+                Some(old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)
+                     .end_point());
 
             let mut err = match (new_loan.kind, old_loan.kind) {
                 (ty::MutBorrow, ty::MutBorrow) =>
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index add128cc2cf..6be07878487 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -47,7 +47,7 @@ use std::rc::Rc;
 use std::hash::{Hash, Hasher};
 use syntax::ast;
 use syntax_pos::{MultiSpan, Span};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
@@ -256,7 +256,7 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>
     {
         self.tcx.sess.struct_span_err_with_code(sp, msg, code)
@@ -755,12 +755,17 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
                                                          s: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a> {
         self.tcx.sess.struct_span_err_with_code(s, msg, code)
     }
 
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(
+        &self,
+        s: S,
+        msg: &str,
+        code: DiagnosticId,
+    ) {
         self.tcx.sess.span_err_with_code(s, msg, code);
     }
 
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 08f3b0a4c5f..6ebe3c67966 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -208,6 +208,20 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
         }
     }
 
+    fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyAdt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(),
+            _ => false,
+        }
+    }
+
+    fn is_local(&self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyAdt(adt_def, ..) => adt_def.did.is_local(),
+            _ => false,
+        }
+    }
+
     fn is_variant_uninhabited(&self,
                               variant: &'tcx ty::VariantDef,
                               substs: &'tcx ty::subst::Substs<'tcx>)
@@ -628,9 +642,16 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
         let is_privately_empty =
             all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
-        debug!("missing_ctors={:?} is_privately_empty={:?}", missing_ctors,
-               is_privately_empty);
-        if missing_ctors.is_empty() && !is_privately_empty {
+        let is_declared_nonexhaustive =
+            cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
+        debug!("missing_ctors={:?} is_privately_empty={:?} is_declared_nonexhaustive={:?}",
+               missing_ctors, is_privately_empty, is_declared_nonexhaustive);
+
+        // For privately empty and non-exhaustive enums, we work as if there were an "extra"
+        // `_` constructor for the type, so we can never match over all constructors.
+        let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
+
+        if missing_ctors.is_empty() && !is_non_exhaustive {
             all_ctors.into_iter().map(|c| {
                 is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
             }).find(|result| result.is_useful()).unwrap_or(NotUseful)
@@ -645,7 +666,51 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             match is_useful(cx, &matrix, &v[1..], witness) {
                 UsefulWithWitness(pats) => {
                     let cx = &*cx;
-                    let new_witnesses = if used_ctors.is_empty() {
+                    // In this case, there's at least one "free"
+                    // constructor that is only matched against by
+                    // wildcard patterns.
+                    //
+                    // There are 2 ways we can report a witness here.
+                    // Commonly, we can report all the "free"
+                    // constructors as witnesses, e.g. if we have:
+                    //
+                    // ```
+                    //     enum Direction { N, S, E, W }
+                    //     let Direction::N = ...;
+                    // ```
+                    //
+                    // we can report 3 witnesses: `S`, `E`, and `W`.
+                    //
+                    // However, there are 2 cases where we don't want
+                    // to do this and instead report a single `_` witness:
+                    //
+                    // 1) If the user is matching against a non-exhaustive
+                    // enum, there is no point in enumerating all possible
+                    // variants, because the user can't actually match
+                    // against them himself, e.g. in an example like:
+                    // ```
+                    //     let err: io::ErrorKind = ...;
+                    //     match err {
+                    //         io::ErrorKind::NotFound => {},
+                    //     }
+                    // ```
+                    // we don't want to show every possible IO error,
+                    // but instead have `_` as the witness (this is
+                    // actually *required* if the user specified *all*
+                    // IO errors, but is probably what we want in every
+                    // case).
+                    //
+                    // 2) If the user didn't actually specify a constructor
+                    // in this arm, e.g. in
+                    // ```
+                    //     let x: (Direction, Direction, bool) = ...;
+                    //     let (_, _, false) = x;
+                    // ```
+                    // we don't want to show all 16 possible witnesses
+                    // `(<direction-1>, <direction-2>, true)` - we are
+                    // satisfied with `(_, _, true)`. In this case,
+                    // `used_ctors` is empty.
+                    let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
                         // All constructors are unused. Add wild patterns
                         // rather than each individual constructor
                         pats.into_iter().map(|mut witness| {
diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs
index b67048939e4..9d820ea8cbe 100644
--- a/src/librustc_const_math/float.rs
+++ b/src/librustc_const_math/float.rs
@@ -203,3 +203,11 @@ impl ::std::ops::Neg for ConstFloat {
         ConstFloat { bits, ty: self.ty }
     }
 }
+
+/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
+/// are rounded to infinity when converted to `f32`.
+///
+/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
+/// shifted by the maximum exponent (accounting for normalization).
+pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
+                                        << (Single::MAX_EXP - Single::PRECISION as i16);
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index e8f9a672087..94edaa746f9 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -145,7 +145,7 @@ pub struct BitMatrix {
 }
 
 impl BitMatrix {
-    // Create a new `rows x columns` matrix, initially empty.
+    /// Create a new `rows x columns` matrix, initially empty.
     pub fn new(rows: usize, columns: usize) -> BitMatrix {
         // For every element, we need one bit for every other
         // element. Round up to an even number of u64s.
@@ -163,9 +163,13 @@ impl BitMatrix {
         (start, start + u64s_per_row)
     }
 
-    pub fn add(&mut self, source: usize, target: usize) -> bool {
-        let (start, _) = self.range(source);
-        let (word, mask) = word_mask(target);
+    /// Sets the cell at `(row, column)` to true. Put another way, add
+    /// `column` to the bitset for `row`.
+    ///
+    /// Returns true if this changed the matrix, and false otherwies.
+    pub fn add(&mut self, row: usize, column: usize) -> bool {
+        let (start, _) = self.range(row);
+        let (word, mask) = word_mask(column);
         let vector = &mut self.vector[..];
         let v1 = vector[start + word];
         let v2 = v1 | mask;
@@ -173,19 +177,19 @@ impl BitMatrix {
         v1 != v2
     }
 
-    /// Do the bits from `source` contain `target`?
-    ///
-    /// Put another way, if the matrix represents (transitive)
-    /// reachability, can `source` reach `target`?
-    pub fn contains(&self, source: usize, target: usize) -> bool {
-        let (start, _) = self.range(source);
-        let (word, mask) = word_mask(target);
+    /// Do the bits from `row` contain `column`? Put another way, is
+    /// the matrix cell at `(row, column)` true?  Put yet another way,
+    /// if the matrix represents (transitive) reachability, can
+    /// `row` reach `column`?
+    pub fn contains(&self, row: usize, column: usize) -> bool {
+        let (start, _) = self.range(row);
+        let (word, mask) = word_mask(column);
         (self.vector[start + word] & mask) != 0
     }
 
-    /// Returns those indices that are reachable from both `a` and
-    /// `b`. This is an O(n) operation where `n` is the number of
-    /// elements (somewhat independent from the actual size of the
+    /// Returns those indices that are true in rows `a` and `b`.  This
+    /// is an O(n) operation where `n` is the number of elements
+    /// (somewhat independent from the actual size of the
     /// intersection, in particular).
     pub fn intersection(&self, a: usize, b: usize) -> Vec<usize> {
         let (a_start, a_end) = self.range(a);
@@ -206,7 +210,7 @@ impl BitMatrix {
         result
     }
 
-    /// Add the bits from `read` to the bits from `write`,
+    /// Add the bits from row `read` to the bits from row `write`,
     /// return true if anything changed.
     ///
     /// This is used when computing transitive reachability because if
@@ -227,6 +231,8 @@ impl BitMatrix {
         changed
     }
 
+    /// Iterates through all the columns set to true in a given row of
+    /// the matrix.
     pub fn iter<'a>(&'a self, row: usize) -> BitVectorIter<'a> {
         let (start, end) = self.range(row);
         BitVectorIter {
diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs
index c790463e47a..c5ffb003399 100644
--- a/src/librustc_data_structures/indexed_set.rs
+++ b/src/librustc_data_structures/indexed_set.rs
@@ -53,11 +53,19 @@ pub struct IdxSet<T: Idx> {
 }
 
 impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        w.debug_list()
+         .entries(self.iter())
+         .finish()
+    }
 }
 
 impl<T: Idx> fmt::Debug for IdxSet<T> {
-    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.bits.fmt(w) }
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        w.debug_list()
+         .entries(self.iter())
+         .finish()
+    }
 }
 
 impl<T: Idx> IdxSetBuf<T> {
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 1d1b367de20..a733e9de5a1 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -45,74 +45,282 @@ macro_rules! newtype_index {
     // Use default constants
     ($name:ident) => (
         newtype_index!(
-            @type[$name]
-            @max[::std::u32::MAX]
-            @debug_name[unsafe {::std::intrinsics::type_name::<$name>() }]);
+            // Leave out derives marker so we can use its absence to ensure it comes first
+            @type         [$name]
+            @max          [::std::u32::MAX]
+            @debug_format ["{}"]);
     );
 
     // Define any constants
     ($name:ident { $($tokens:tt)+ }) => (
         newtype_index!(
-            @type[$name]
-            @max[::std::u32::MAX]
-            @debug_name[unsafe {::std::intrinsics::type_name::<$name>() }]
-            $($tokens)+);
+            // Leave out derives marker so we can use its absence to ensure it comes first
+            @type         [$name]
+            @max          [::std::u32::MAX]
+            @debug_format ["{}"]
+                          $($tokens)+);
     );
 
     // ---- private rules ----
 
     // Base case, user-defined constants (if any) have already been defined
-    (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]) => (
-        #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
-            RustcEncodable, RustcDecodable)]
-        pub struct $type(pub u32);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]) => (
+        #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
+        pub struct $type($($pub)* u32);
 
         impl Idx for $type {
             fn new(value: usize) -> Self {
                 assert!(value < ($max) as usize);
                 $type(value as u32)
             }
+
             fn index(self) -> usize {
                 self.0 as usize
             }
         }
 
+        newtype_index!(
+            @handle_debug
+            @derives      [$($derives,)*]
+            @type         [$type]
+            @debug_format [$debug_format]);
+    );
+
+    // base case for handle_debug where format is custom. No Debug implementation is emitted.
+    (@handle_debug
+     @derives      [$($_derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [custom]) => ();
+
+    // base case for handle_debug, no debug overrides found, so use default
+    (@handle_debug
+     @derives      []
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => (
         impl ::std::fmt::Debug for $type {
             fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
-                write!(fmt, "{}{}", $debug_name, self.0)
+                write!(fmt, $debug_format, self.0)
             }
         }
     );
 
+    // Debug is requested for derive, don't generate any Debug implementation.
+    (@handle_debug
+     @derives      [Debug, $($derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => ();
+
+    // It's not Debug, so just pop it off the front of the derives stack and check the rest.
+    (@handle_debug
+     @derives      [$_derive:ident, $($derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => (
+        newtype_index!(
+            @handle_debug
+            @derives      [$($derives,)*]
+            @type         [$type]
+            @debug_format [$debug_format]);
+    );
+
+    // Handle the case where someone wants to make the internal field public
+    (@type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   pub idx
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          [pub]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The default case is that the internal field is private
+    (@type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          []
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // Append comma to end of derives list if it's missing
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident),*]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          derive [$($derives,)*]
+                          $($tokens)*);
+    );
+
+    // By not including the @derives marker in this list nor in the default args, we can force it
+    // to come first if it exists. When encodable is custom, just use the derives list as-is.
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident,)+]
+                   ENCODABLE = custom
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)+]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // By not including the @derives marker in this list nor in the default args, we can force it
+    // to come first if it exists. When encodable isn't custom, add serialization traits by default.
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident,)+]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)+ RustcDecodable, RustcEncodable,]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The case where no derives are added, but encodable is overriden. Don't
+    // derive serialization traits
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   ENCODABLE = custom
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      []
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The case where no derives are added, add serialization derives by default
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [RustcDecodable, RustcEncodable,]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
     // Rewrite final without comma to one that includes comma
-    (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]
-            $name:ident = $constant:expr) => (
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $name = $constant,);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $name:ident = $constant:expr) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $name = $constant,);
     );
 
     // Rewrite final const without comma to one that includes comma
-    (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
-            const $name:ident = $constant:expr) => (
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] const $name = $constant,);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$_max:expr]
+     @debug_format [$debug_format:tt]
+                   $(#[doc = $doc:expr])*
+                   const $name:ident = $constant:expr) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $(#[doc = $doc])* const $name = $constant,);
     );
 
     // Replace existing default for max
-    (@type[$type:ident] @max[$_max:expr] @debug_name[$debug_name:expr]
-            MAX = $max:expr, $($tokens:tt)*) => (
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$_max:expr]
+     @debug_format [$debug_format:tt]
+                   MAX = $max:expr,
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 
-    // Replace existing default for debug_name
-    (@type[$type:ident] @max[$max:expr] @debug_name[$_debug_name:expr]
-            DEBUG_NAME = $debug_name:expr, $($tokens:tt)*) => (
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
+    // Replace existing default for debug_format
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$_debug_format:tt]
+                   DEBUG_FORMAT = $debug_format:tt,
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 
-    // Assign a user-defined constant (as final param)
-    (@type[$type:ident] @max[$max:expr] @debug_name[$debug_name:expr]
-            const $name:ident = $constant:expr, $($tokens:tt)*) => (
+    // Assign a user-defined constant
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $(#[doc = $doc:expr])*
+                   const $name:ident = $constant:expr,
+                   $($tokens:tt)*) => (
+        $(#[doc = $doc])*
         pub const $name: $type = $type($constant);
-        newtype_index!(@type[$type] @max[$max] @debug_name[$debug_name] $($tokens)*);
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 }
 
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index 7cb386b0197..933e08811ce 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -134,12 +134,12 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
         }
     }
 
-    /// Returns a vector of all things less than `a`.
+    /// Returns a vector of all things greater than `a`.
     ///
     /// Really this probably ought to be `impl Iterator<Item=&T>`, but
     /// I'm too lazy to make that work, and -- given the caching
     /// strategy -- it'd be a touch tricky anyhow.
-    pub fn less_than(&self, a: &T) -> Vec<&T> {
+    pub fn greater_than(&self, a: &T) -> Vec<&T> {
         match self.index(a) {
             Some(a) => self.with_closure(|closure| {
                 closure.iter(a.0).map(|i| &self.elements[i]).collect()
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index cd3740f72e0..855362cf645 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -940,6 +940,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     let time_passes = sess.time_passes();
 
+    let query_result_on_disk_cache = time(time_passes,
+        "load query result cache",
+        || rustc_incremental::load_query_result_cache(sess));
+
     let named_region_map = time(time_passes,
                                 "lifetime resolution",
                                 || middle::resolve_lifetime::krate(sess, cstore, &hir_map))?;
@@ -1003,7 +1007,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
     passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
-    passes.push_pass(MIR_VALIDATED, mir::transform::nll::NLL);
 
     // borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
 
@@ -1048,6 +1051,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                              resolutions,
                              named_region_map,
                              hir_map,
+                             query_result_on_disk_cache,
                              name,
                              tx,
                              output_filenames,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index fc503f4eb4b..c5cce70c945 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -177,6 +177,7 @@ mod rustc_trans {
         pub mod write {
             pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
             pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
+            pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
         }
     }
 }
@@ -797,6 +798,13 @@ impl RustcDefaultCalls {
                     }
                     println!("");
                 }
+                PrintRequest::TlsModels => {
+                    println!("Available TLS models:");
+                    for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
+                        println!("    {}", name);
+                    }
+                    println!("");
+                }
                 PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
                     rustc_trans::print(*req, sess);
                 }
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 6de36820f0c..5ff75351b63 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -23,6 +23,7 @@ use rustc::middle::resolve_lifetime;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::traits::{ObligationCause, Reveal};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::maps::OnDiskCache;
 use rustc::infer::{self, InferOk, InferResult};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc_metadata::cstore::CStore;
@@ -156,6 +157,7 @@ fn test_env<F>(source_string: &str,
                              resolutions,
                              named_region_map.unwrap(),
                              hir_map,
+                             OnDiskCache::new_empty(sess.codemap()),
                              "test_crate",
                              tx,
                              &outputs,
@@ -251,7 +253,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
                 hir::ItemImpl(..) |
-                hir::ItemDefaultImpl(..) => None,
+                hir::ItemAutoImpl(..) => None,
 
                 hir::ItemMod(ref m) => search_mod(this, m, idx, names),
             };
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 5e0e624082e..2d70de89355 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -21,12 +21,18 @@ use snippet::Style;
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
-    pub code: Option<String>,
+    pub code: Option<DiagnosticId>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Vec<CodeSuggestion>,
 }
 
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum DiagnosticId {
+    Error(String),
+    Lint(String),
+}
+
 /// For example a note attached to an error.
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct SubDiagnostic {
@@ -81,7 +87,7 @@ impl Diagnostic {
         Diagnostic::new_with_code(level, None, message)
     }
 
-    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
+    pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) -> Self {
         Diagnostic {
             level,
             message: vec![(message.to_owned(), Style::NoStyle)],
@@ -267,7 +273,7 @@ impl Diagnostic {
         self
     }
 
-    pub fn code(&mut self, s: String) -> &mut Self {
+    pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
         self.code = Some(s);
         self
     }
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 2cd433bfe3a..40b5810454b 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use Diagnostic;
+use DiagnosticId;
 use DiagnosticStyledString;
 
 use Level;
@@ -192,7 +193,7 @@ impl<'a> DiagnosticBuilder<'a> {
                                      suggestions: Vec<String>)
                                      -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
-    forward!(pub fn code(&mut self, s: String) -> &mut Self);
+    forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
     /// Convenience function for internal use, clients should use one of the
     /// struct_* methods on Handler.
@@ -204,7 +205,7 @@ impl<'a> DiagnosticBuilder<'a> {
     /// struct_* methods on Handler.
     pub fn new_with_code(handler: &'a Handler,
                          level: Level,
-                         code: Option<String>,
+                         code: Option<DiagnosticId>,
                          message: &str)
                          -> DiagnosticBuilder<'a> {
         let diagnostic = Diagnostic::new_with_code(level, code, message);
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 5db5a9a1133..6c43c60686e 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -10,9 +10,9 @@
 
 use self::Destination::*;
 
-use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan, CharPos};
+use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
 
-use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper};
+use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId};
 use RenderSpan::*;
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
@@ -201,8 +201,8 @@ impl EmitterWriter {
                 // 6..7. This is degenerate input, but it's best to degrade
                 // gracefully -- and the parser likes to supply a span like
                 // that for EOF, in particular.
-                if lo.col == hi.col && lo.line == hi.line {
-                    hi.col = CharPos(lo.col.0 + 1);
+                if lo.col_display == hi.col_display && lo.line == hi.line {
+                    hi.col_display += 1;
                 }
 
                 let ann_type = if lo.line != hi.line {
@@ -210,8 +210,8 @@ impl EmitterWriter {
                         depth: 1,
                         line_start: lo.line,
                         line_end: hi.line,
-                        start_col: lo.col.0,
-                        end_col: hi.col.0,
+                        start_col: lo.col_display,
+                        end_col: hi.col_display,
                         is_primary: span_label.is_primary,
                         label: span_label.label.clone(),
                     };
@@ -221,8 +221,8 @@ impl EmitterWriter {
                     AnnotationType::Singleline
                 };
                 let ann = Annotation {
-                    start_col: lo.col.0,
-                    end_col: hi.col.0,
+                    start_col: lo.col_display,
+                    end_col: hi.col_display,
                     is_primary: span_label.is_primary,
                     label: span_label.label.clone(),
                     annotation_type: ann_type,
@@ -886,7 +886,7 @@ impl EmitterWriter {
     fn emit_message_default(&mut self,
                             msp: &MultiSpan,
                             msg: &Vec<(String, Style)>,
-                            code: &Option<String>,
+                            code: &Option<DiagnosticId>,
                             level: &Level,
                             max_line_num_len: usize,
                             is_secondary: bool)
@@ -905,13 +905,11 @@ impl EmitterWriter {
             self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
         } else {
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
-            match code {
-                &Some(ref code) => {
-                    buffer.append(0, "[", Style::Level(level.clone()));
-                    buffer.append(0, &code, Style::Level(level.clone()));
-                    buffer.append(0, "]", Style::Level(level.clone()));
-                }
-                _ => {}
+            // only render error codes, not lint codes
+            if let Some(DiagnosticId::Error(ref code)) = *code {
+                buffer.append(0, "[", Style::Level(level.clone()));
+                buffer.append(0, &code, Style::Level(level.clone()));
+                buffer.append(0, "]", Style::Level(level.clone()));
             }
             buffer.append(0, ": ", Style::HeaderMsg);
             for &(ref text, _) in msg.iter() {
@@ -1174,7 +1172,7 @@ impl EmitterWriter {
     fn emit_messages_default(&mut self,
                              level: &Level,
                              message: &Vec<(String, Style)>,
-                             code: &Option<String>,
+                             code: &Option<DiagnosticId>,
                              span: &MultiSpan,
                              children: &Vec<SubDiagnostic>) {
         let max_line_num = self.get_max_line_num(span, children);
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index ba7268a4bc3..b30ee7016ab 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -262,7 +262,7 @@ impl error::Error for ExplicitBug {
     }
 }
 
-pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString};
+pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, DiagnosticId};
 pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
@@ -337,11 +337,11 @@ impl Handler {
     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                               sp: S,
                                                               msg: &str,
-                                                              code: &str)
+                                                              code: DiagnosticId)
                                                               -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         if !self.can_emit_warnings {
             result.cancel();
         }
@@ -365,20 +365,24 @@ impl Handler {
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
-                                                             code: &str)
+                                                             code: DiagnosticId)
                                                              -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         DiagnosticBuilder::new(self, Level::Error, msg)
     }
-    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err_with_code<'a>(
+        &'a self,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
@@ -392,11 +396,11 @@ impl Handler {
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
-                                                               code: &str)
+                                                               code: DiagnosticId)
                                                                -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
@@ -420,7 +424,7 @@ impl Handler {
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
                                                     sp: S,
                                                     msg: &str,
-                                                    code: &str)
+                                                    code: DiagnosticId)
                                                     -> FatalError {
         self.emit_with_code(&sp.into(), msg, code, Fatal);
         FatalError
@@ -436,13 +440,13 @@ impl Handler {
         result.set_span(sp);
         result
     }
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.emit_with_code(&sp.into(), msg, code, Error);
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Warning);
     }
-    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.emit_with_code(&sp.into(), msg, code, Warning);
     }
     pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
@@ -546,11 +550,11 @@ impl Handler {
             self.abort_if_errors();
         }
     }
-    pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: &str, lvl: Level) {
+    pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl: Level) {
         if lvl == Warning && !self.can_emit_warnings {
             return;
         }
-        let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code.to_owned()), msg);
+        let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg);
         db.set_span(msp.clone());
         db.emit();
         if !self.continue_after_error.get() {
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 0294adb3f5d..e82c2897d21 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -17,6 +17,9 @@
 
 #![feature(rand)]
 #![feature(conservative_impl_trait)]
+#![feature(i128_type)]
+#![feature(inclusive_range_syntax)]
+#![feature(specialization)]
 
 extern crate graphviz;
 #[macro_use] extern crate rustc;
@@ -31,8 +34,9 @@ mod assert_dep_graph;
 mod persist;
 
 pub use assert_dep_graph::assert_dep_graph;
-pub use persist::load_dep_graph;
 pub use persist::dep_graph_tcx_init;
+pub use persist::load_dep_graph;
+pub use persist::load_query_result_cache;
 pub use persist::save_dep_graph;
 pub use persist::save_trans_partition;
 pub use persist::save_work_products;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 0cb920a111d..e871c0dbdab 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -409,7 +409,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
                     //HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT),
 
                     // `impl Trait for .. {}`
-                    HirItem::ItemDefaultImpl(..) => ("ItemDefaultImpl", LABELS_IMPL),
+                    HirItem::ItemAutoImpl(..) => ("ItemAutoImpl", LABELS_IMPL),
 
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
                     HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL),
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index 89310b9d6f5..458f47a1602 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -131,6 +131,7 @@ const LOCK_FILE_EXT: &'static str = ".lock";
 const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
 const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
 const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
+const QUERY_CACHE_FILENAME: &'static str = "query-cache.bin";
 
 // We encode integers using the following base, so they are shorter than decimal
 // or hexadecimal numbers (we want short file and directory names). Since these
@@ -150,6 +151,10 @@ pub fn metadata_hash_export_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, METADATA_HASHES_FILENAME)
 }
 
+pub fn query_cache_path(sess: &Session) -> PathBuf {
+    in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME)
+}
+
 pub fn lock_file_path(session_dir: &Path) -> PathBuf {
     let crate_dir = session_dir.parent().unwrap();
 
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 63cfbcac145..158e9f2677a 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -15,6 +15,7 @@ use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc::ty::maps::OnDiskCache;
 use rustc::util::nodemap::DefIdMap;
 use rustc_serialize::Decodable as RustcDecodable;
 use rustc_serialize::opaque::Decoder;
@@ -195,3 +196,15 @@ pub fn load_dep_graph(sess: &Session) -> PreviousDepGraph {
         empty
     }
 }
+
+pub fn load_query_result_cache<'sess>(sess: &'sess Session) -> OnDiskCache<'sess> {
+    if sess.opts.incremental.is_none() {
+        return OnDiskCache::new_empty(sess.codemap());
+    }
+
+    if let Some(bytes) = load_data(sess, &query_cache_path(sess)) {
+        OnDiskCache::new(sess, &bytes[..])
+    } else {
+        OnDiskCache::new_empty(sess.codemap())
+    }
+}
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index 88d49e7aedc..82a43d85bc6 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -23,8 +23,9 @@ mod file_format;
 pub use self::fs::prepare_session_directory;
 pub use self::fs::finalize_session_directory;
 pub use self::fs::in_incr_comp_dir;
-pub use self::load::load_dep_graph;
 pub use self::load::dep_graph_tcx_init;
+pub use self::load::load_dep_graph;
+pub use self::load::load_query_result_cache;
 pub use self::save::save_dep_graph;
 pub use self::save::save_work_products;
 pub use self::work_product::save_trans_partition;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index b9f73500e27..711550c27d1 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -63,6 +63,12 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            e));
     }
 
+    time(sess.time_passes(), "persist query result cache", || {
+        save_in(sess,
+                query_cache_path(sess),
+                |e| encode_query_cache(tcx, e));
+    });
+
     time(sess.time_passes(), "persist dep-graph", || {
         save_in(sess,
                 dep_graph_path(sess),
@@ -298,3 +304,9 @@ fn encode_work_products(dep_graph: &DepGraph,
 
     work_products.encode(encoder)
 }
+
+fn encode_query_cache(tcx: TyCtxt,
+                      encoder: &mut Encoder)
+                      -> io::Result<()> {
+    tcx.serialize_query_result_cache(encoder)
+}
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 027ed84faf0..d14a6943fc1 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -23,7 +23,7 @@ use rustc::hir::intravisit::FnKind;
 
 #[derive(PartialEq)]
 pub enum MethodLateContext {
-    TraitDefaultImpl,
+    TraitAutoImpl,
     TraitImpl,
     PlainImpl,
 }
@@ -32,7 +32,7 @@ pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
     let def_id = cx.tcx.hir.local_def_id(id);
     let item = cx.tcx.associated_item(def_id);
     match item.container {
-        ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
+        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
         ty::ImplContainer(cid) => {
             match cx.tcx.impl_trait_ref(cid) {
                 Some(_) => MethodLateContext::TraitImpl,
@@ -245,7 +245,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
                     MethodLateContext::PlainImpl => {
                         self.check_snake_case(cx, "method", &name.as_str(), Some(span))
                     }
-                    MethodLateContext::TraitDefaultImpl => {
+                    MethodLateContext::TraitAutoImpl => {
                         self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
                     }
                     _ => (),
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 70cac419648..07874a8cc69 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -56,6 +56,31 @@ use bad_style::{MethodLateContext, method_context};
 pub use lint::builtin::*;
 
 declare_lint! {
+    pub AUTO_IMPL,
+    Deny,
+    "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`"
+}
+
+#[derive(Copy, Clone)]
+pub struct AutoImpl;
+
+impl LintPass for AutoImpl {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(AUTO_IMPL)
+    }
+}
+
+impl EarlyLintPass for AutoImpl {
+    fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
+        let msg = "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`";
+        match item.node {
+            ast::ItemKind::AutoImpl(..) => cx.span_lint(AUTO_IMPL, item.span, msg),
+            _ => ()
+        }
+     }
+}
+
+declare_lint! {
     WHILE_TRUE,
     Warn,
     "suggest using `loop { }` instead of `while true { }`"
@@ -228,7 +253,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnsafeCode {
 
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
-            hir::ItemTrait(hir::Unsafety::Unsafe, ..) => {
+            hir::ItemTrait(_, hir::Unsafety::Unsafe, ..) => {
                 self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
             }
 
@@ -1301,3 +1326,60 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
         }
     }
 }
+
+/// Lint for items marked `pub` that aren't reachable from other crates
+pub struct UnreachablePub;
+
+declare_lint! {
+    UNREACHABLE_PUB,
+    Allow,
+    "`pub` items not reachable from crate root"
+}
+
+impl LintPass for UnreachablePub {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNREACHABLE_PUB)
+    }
+}
+
+impl UnreachablePub {
+    fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
+                    vis: &hir::Visibility, span: Span, exportable: bool) {
+        if !cx.access_levels.is_reachable(id) && *vis == hir::Visibility::Public {
+            let def_span = cx.tcx.sess.codemap().def_span(span);
+            let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
+                                              &format!("unreachable `pub` {}", what));
+            // visibility is token at start of declaration (can be macro
+            // variable rather than literal `pub`)
+            let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
+            let replacement = if cx.tcx.sess.features.borrow().crate_visibility_modifier {
+                "crate"
+            } else {
+                "pub(crate)"
+            }.to_owned();
+            err.span_suggestion(pub_span, "consider restricting its visibility", replacement);
+            if exportable {
+                err.help("or consider exporting it for use by other crates");
+            }
+            err.emit();
+        }
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
+        self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+    }
+
+    fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) {
+        self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis, foreign_item.span, true);
+    }
+
+    fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
+        self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
+        self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+    }
+}
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 42fcf377d65..1a8ad9718cf 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -109,6 +109,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                        AnonymousParameters,
                        IllegalFloatLiteralPattern,
                        UnusedDocComment,
+                       AutoImpl,
                        );
 
     add_early_builtin_with_new!(sess,
@@ -137,6 +138,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                  PluginAsLibrary,
                  MutableTransmutes,
                  UnionsWithDropFields,
+                 UnreachablePub,
                  );
 
     add_builtin_with_new!(sess,
@@ -182,6 +184,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     store.register_future_incompatible(sess,
                                        vec![
         FutureIncompatibleInfo {
+            id: LintId::of(AUTO_IMPL),
+            reference: "issue #13231 <https://github.com/rust-lang/rust/issues/13231>",
+        },
+        FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
         },
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index 3399bf2acd8..ac0e4dde0c1 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -359,6 +359,17 @@ pub struct ThinLTOModule {
     pub len: usize,
 }
 
+/// LLVMThreadLocalMode
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub enum ThreadLocalMode {
+  NotThreadLocal,
+  GeneralDynamic,
+  LocalDynamic,
+  InitialExec,
+  LocalExec
+}
+
 // Opaque pointer types
 #[allow(missing_copy_implementations)]
 pub enum Module_opaque {}
@@ -709,6 +720,7 @@ extern "C" {
     pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef;
     pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef);
     pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool);
+    pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode);
     pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool;
     pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool);
     pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef;
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 98172bca177..5ccce8de706 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -172,6 +172,11 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
         LLVMSetThreadLocal(global, is_thread_local as Bool);
     }
 }
+pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
+    unsafe {
+        LLVMSetThreadLocalMode(global, mode);
+    }
+}
 
 impl Attribute {
     pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index cfc8d271327..155097cdbe2 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -258,14 +258,15 @@ impl<'a> CrateLoader<'a> {
         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
 
         let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
-            crate_root.def_path_table.decode(&metadata)
+            crate_root.def_path_table.decode((&metadata, self.sess))
         });
 
-        let exported_symbols = crate_root.exported_symbols.decode(&metadata).collect();
-
+        let exported_symbols = crate_root.exported_symbols
+                                         .decode((&metadata, self.sess))
+                                         .collect();
         let trait_impls = crate_root
             .impls
-            .decode(&metadata)
+            .decode((&metadata, self.sess))
             .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
             .collect();
 
@@ -298,7 +299,7 @@ impl<'a> CrateLoader<'a> {
         let dllimports: FxHashSet<_> = cmeta
             .root
             .native_libraries
-            .decode(&cmeta)
+            .decode((&cmeta, self.sess))
             .filter(|lib| relevant_lib(self.sess, lib) &&
                           lib.kind == cstore::NativeLibraryKind::NativeUnknown)
             .flat_map(|lib| {
@@ -685,14 +686,15 @@ impl<'a> CrateLoader<'a> {
         let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
                                                           "needs_panic_runtime");
 
+        let sess = self.sess;
         self.cstore.iter_crate_data(|cnum, data| {
             needs_panic_runtime = needs_panic_runtime ||
-                                  data.needs_panic_runtime();
-            if data.is_panic_runtime() {
+                                  data.needs_panic_runtime(sess);
+            if data.is_panic_runtime(sess) {
                 // Inject a dependency from all #![needs_panic_runtime] to this
                 // #![panic_runtime] crate.
                 self.inject_dependency_if(cnum, "a panic runtime",
-                                          &|data| data.needs_panic_runtime());
+                                          &|data| data.needs_panic_runtime(sess));
                 runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
             }
         });
@@ -728,7 +730,7 @@ impl<'a> CrateLoader<'a> {
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
         // and the panic strategy is indeed what we thought it was.
-        if !data.is_panic_runtime() {
+        if !data.is_panic_runtime(self.sess) {
             self.sess.err(&format!("the crate `{}` is not a panic runtime",
                                    name));
         }
@@ -740,7 +742,7 @@ impl<'a> CrateLoader<'a> {
 
         self.sess.injected_panic_runtime.set(Some(cnum));
         self.inject_dependency_if(cnum, "a panic runtime",
-                                  &|data| data.needs_panic_runtime());
+                                  &|data| data.needs_panic_runtime(self.sess));
     }
 
     fn inject_sanitizer_runtime(&mut self) {
@@ -835,7 +837,7 @@ impl<'a> CrateLoader<'a> {
                                        PathKind::Crate, dep_kind);
 
                 // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime
-                if !data.is_sanitizer_runtime() {
+                if !data.is_sanitizer_runtime(self.sess) {
                     self.sess.err(&format!("the crate `{}` is not a sanitizer runtime",
                                            name));
                 }
@@ -856,7 +858,7 @@ impl<'a> CrateLoader<'a> {
                                    PathKind::Crate, dep_kind);
 
             // Sanity check the loaded crate to ensure it is indeed a profiler runtime
-            if !data.is_profiler_runtime() {
+            if !data.is_profiler_runtime(self.sess) {
                 self.sess.err(&format!("the crate `profiler_builtins` is not \
                                         a profiler runtime"));
             }
@@ -875,7 +877,7 @@ impl<'a> CrateLoader<'a> {
         let mut needs_allocator = attr::contains_name(&krate.attrs,
                                                       "needs_allocator");
         self.cstore.iter_crate_data(|_, data| {
-            needs_allocator = needs_allocator || data.needs_allocator();
+            needs_allocator = needs_allocator || data.needs_allocator(self.sess);
         });
         if !needs_allocator {
             return
@@ -997,7 +999,7 @@ impl<'a> CrateLoader<'a> {
             Some(data) => {
                 // We have an allocator. We detect separately what kind it is, to allow for some
                 // flexibility in misconfiguration.
-                let attrs = data.get_item_attrs(CRATE_DEF_INDEX);
+                let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess);
                 let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind")
                     .map(Symbol::as_str);
                 let kind_str = kind_interned
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index c688b4c408a..a86b55e269d 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
-use rustc::session::CrateDisambiguator;
+use rustc::session::{Session, CrateDisambiguator};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
@@ -176,8 +176,8 @@ impl CrateMetadata {
         self.root.disambiguator
     }
 
-    pub fn needs_allocator(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_allocator(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "needs_allocator")
     }
 
@@ -189,43 +189,43 @@ impl CrateMetadata {
         self.root.has_default_lib_allocator.clone()
     }
 
-    pub fn is_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_panic_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "panic_runtime")
     }
 
-    pub fn needs_panic_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn needs_panic_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "needs_panic_runtime")
     }
 
-    pub fn is_compiler_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_compiler_builtins(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "compiler_builtins")
     }
 
-    pub fn is_sanitizer_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_sanitizer_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "sanitizer_runtime")
     }
 
-    pub fn is_profiler_runtime(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_profiler_runtime(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "profiler_runtime")
     }
 
-    pub fn is_no_builtins(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn is_no_builtins(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_name(&attrs, "no_builtins")
     }
 
-     pub fn has_copy_closures(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+     pub fn has_copy_closures(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_feature_attr(&attrs, "copy_closures")
     }
 
-    pub fn has_clone_closures(&self) -> bool {
-        let attrs = self.get_item_attrs(CRATE_DEF_INDEX);
+    pub fn has_clone_closures(&self, sess: &Session) -> bool {
+        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
         attr::contains_feature_attr(&attrs, "clone_closures")
     }
 
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index fbe63e0ab4a..8dcfb4c34b5 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -99,11 +99,13 @@ impl IntoArgs for (CrateNum, DefId) {
 
 provide! { <'tcx> tcx, def_id, other, cdata,
     type_of => { cdata.get_type(def_id.index, tcx) }
-    generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) }
+    generics_of => {
+        tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
+    }
     predicates_of => { cdata.get_predicates(def_id.index, tcx) }
     super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
     trait_def => {
-        tcx.alloc_trait_def(cdata.get_trait_def(def_id.index))
+        tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
     }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
     adt_destructor => {
@@ -144,7 +146,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
-    is_default_impl => { cdata.is_default_impl(def_id.index) }
+    is_auto_impl => { cdata.is_auto_impl(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
     lookup_stability => {
@@ -153,7 +155,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     lookup_deprecation_entry => {
         cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
     }
-    item_attrs => { cdata.get_item_attrs(def_id.index) }
+    item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) }
     // FIXME(#38501) We've skipped a `read` on the `HirBody` of
     // a `fn` when encoding, so the dep-tracking wouldn't work.
     // This is only used by rustdoc anyway, which shouldn't have
@@ -171,17 +173,17 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
 
     dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats()) }
-    is_panic_runtime => { cdata.is_panic_runtime() }
-    is_compiler_builtins => { cdata.is_compiler_builtins() }
+    is_panic_runtime => { cdata.is_panic_runtime(tcx.sess) }
+    is_compiler_builtins => { cdata.is_compiler_builtins(tcx.sess) }
     has_global_allocator => { cdata.has_global_allocator() }
-    is_sanitizer_runtime => { cdata.is_sanitizer_runtime() }
-    is_profiler_runtime => { cdata.is_profiler_runtime() }
+    is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
+    is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
     panic_strategy => { cdata.panic_strategy() }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
-    is_no_builtins => { cdata.is_no_builtins() }
+    is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
     impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
     exported_symbol_ids => { Rc::new(cdata.get_exported_symbols()) }
-    native_libraries => { Rc::new(cdata.get_native_libraries()) }
+    native_libraries => { Rc::new(cdata.get_native_libraries(tcx.sess)) }
     plugin_registrar_fn => {
         cdata.root.plugin_registrar_fn.map(|index| {
             DefId { krate: def_id.krate, index }
@@ -237,8 +239,8 @@ provide! { <'tcx> tcx, def_id, other, cdata,
 
     used_crate_source => { Rc::new(cdata.source.clone()) }
 
-    has_copy_closures => { cdata.has_copy_closures() }
-    has_clone_closures => { cdata.has_clone_closures() }
+    has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
+    has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
 }
 
 pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
@@ -358,8 +360,8 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(def.krate).get_visibility(def.index)
     }
 
-    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics {
-        self.get_crate_data(def.krate).get_generics(def.index)
+    fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics {
+        self.get_crate_data(def.krate).get_generics(def.index, sess)
     }
 
     fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
@@ -454,7 +456,7 @@ impl CrateStore for cstore::CStore {
         let body = filemap_to_stream(&sess.parse_sess, filemap, None);
 
         // Mark the attrs as used
-        let attrs = data.get_item_attrs(id.index);
+        let attrs = data.get_item_attrs(id.index, sess);
         for attr in attrs.iter() {
             attr::mark_used(attr);
         }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 909e01376b9..e63037f4da1 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -25,6 +25,7 @@ use rustc::ich::Fingerprint;
 use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::codec::{self as ty_codec, TyDecoder};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::DefIdSet;
 
@@ -40,6 +41,7 @@ use std::str;
 use std::u32;
 
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
+use rustc_data_structures::indexed_vec::Idx;
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
@@ -85,6 +87,20 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
     }
 }
 
+
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'a Session) {
+    fn raw_bytes(self) -> &'a [u8] {
+        let (blob, _) = self;
+        &blob.0
+    }
+
+    fn sess(self) -> Option<&'a Session> {
+        let (_, sess) = self;
+        Some(sess)
+    }
+}
+
+
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
     fn raw_bytes(self) -> &'a [u8] {
         self.blob.raw_bytes()
@@ -143,16 +159,6 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
-    fn with_position<F: FnOnce(&mut Self) -> R, R>(&mut self, pos: usize, f: F) -> R {
-        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
-        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
-        let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
-        let r = f(self);
-        self.opaque = old_opaque;
-        self.lazy_state = old_state;
-        r
-    }
-
     fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> {
         let distance = self.read_usize()?;
         let position = match self.lazy_state {
@@ -208,6 +214,60 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
     }
 }
 
+
+impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
+
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+        self.tcx.expect("missing TyCtxt in DecodeContext")
+    }
+
+    fn peek_byte(&self) -> u8 {
+        self.opaque.data[self.opaque.position()]
+    }
+
+    fn cached_ty_for_shorthand<F>(&mut self,
+                                  shorthand: usize,
+                                  or_insert_with: F)
+                                  -> Result<Ty<'tcx>, Self::Error>
+        where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>
+    {
+        let tcx = self.tcx();
+
+        let key = ty::CReaderCacheKey {
+            cnum: self.cdata().cnum,
+            pos: shorthand,
+        };
+
+        if let Some(&ty) = tcx.rcache.borrow().get(&key) {
+            return Ok(ty);
+        }
+
+        let ty = or_insert_with(self)?;
+        tcx.rcache.borrow_mut().insert(key, ty);
+        Ok(ty)
+    }
+
+    fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
+        where F: FnOnce(&mut Self) -> R
+    {
+        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
+        let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
+        let r = f(self);
+        self.opaque = old_opaque;
+        self.lazy_state = old_state;
+        r
+    }
+
+    fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
+        if cnum == LOCAL_CRATE {
+            self.cdata().cnum
+        } else {
+            self.cdata().cnum_map.borrow()[cnum]
+        }
+    }
+}
+
 impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
         Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
@@ -245,7 +305,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
         let sess = if let Some(sess) = self.sess {
             sess
         } else {
-            return Ok(Span::new(lo, hi, NO_EXPANSION));
+            bug!("Cannot decode Span without Session.")
         };
 
         let (lo, hi) = if lo > hi {
@@ -267,7 +327,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
             // originate from the same filemap.
             let last_filemap = &imported_filemaps[self.last_filemap_index];
 
-            if lo >= last_filemap.original_start_pos && lo <= last_filemap.original_end_pos &&
+            if lo >= last_filemap.original_start_pos &&
+               lo <= last_filemap.original_end_pos &&
                hi >= last_filemap.original_start_pos &&
                hi <= last_filemap.original_end_pos {
                 last_filemap
@@ -289,8 +350,8 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
             }
         };
 
-        let lo = (lo - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
-        let hi = (hi - filemap.original_start_pos) + filemap.translated_filemap.start_pos;
+        let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
+        let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos;
 
         Ok(Span::new(lo, hi, NO_EXPANSION))
     }
@@ -302,73 +363,37 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
 
 impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
-        let tcx = self.tcx();
-
-        // Handle shorthands first, if we have an usize > 0x80.
-        if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
-            let pos = self.read_usize()?;
-            assert!(pos >= SHORTHAND_OFFSET);
-            let key = ty::CReaderCacheKey {
-                cnum: self.cdata().cnum,
-                pos: pos - SHORTHAND_OFFSET,
-            };
-            if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
-                return Ok(ty);
-            }
-
-            let ty = self.with_position(key.pos, Ty::decode)?;
-            tcx.rcache.borrow_mut().insert(key, ty);
-            Ok(ty)
-        } else {
-            Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?))
-        }
+        ty_codec::decode_ty(self)
     }
 }
 
-
 impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
-        Ok(ty::GenericPredicates {
-            parent: Decodable::decode(self)?,
-            predicates: (0..self.read_usize()?).map(|_| {
-                    // Handle shorthands first, if we have an usize > 0x80.
-                    if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
-                        let pos = self.read_usize()?;
-                        assert!(pos >= SHORTHAND_OFFSET);
-                        let pos = pos - SHORTHAND_OFFSET;
-
-                        self.with_position(pos, ty::Predicate::decode)
-                    } else {
-                        ty::Predicate::decode(self)
-                    }
-                })
-                .collect::<Result<Vec<_>, _>>()?,
-        })
+        ty_codec::decode_predicates(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
-        Ok(self.tcx().mk_substs((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
+        ty_codec::decode_substs(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<ty::Region<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
-        Ok(self.tcx().mk_region(Decodable::decode(self)?))
+        ty_codec::decode_region(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
-        Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
+        ty_codec::decode_ty_slice(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::AdtDef> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
-        let def_id = DefId::decode(self)?;
-        Ok(self.tcx().adt_def(def_id))
+        ty_codec::decode_adt_def(self)
     }
 }
 
@@ -376,22 +401,19 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>
     for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self)
         -> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
-        Ok(self.tcx().mk_existential_predicates((0..self.read_usize()?)
-                                                .map(|_| Decodable::decode(self)))?)
+        ty_codec::decode_existential_predicate_slice(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
-        Ok(ByteArray {
-            data: self.tcx().alloc_byte_array(&Vec::decode(self)?)
-        })
+        ty_codec::decode_byte_array(self)
     }
 }
 
 impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Const<'tcx>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-        Ok(self.tcx().mk_const(Decodable::decode(self)?))
+        ty_codec::decode_const(self)
     }
 }
 
@@ -453,7 +475,7 @@ impl<'tcx> EntryKind<'tcx> {
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
-            EntryKind::DefaultImpl(_) |
+            EntryKind::AutoImpl(_) |
             EntryKind::Field |
             EntryKind::Generator(_) |
             EntryKind::Closure(_) => return None,
@@ -514,16 +536,16 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_trait_def(&self, item_id: DefIndex) -> ty::TraitDef {
+    pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
         let data = match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode(self),
+            EntryKind::Trait(data) => data.decode((self, sess)),
             _ => bug!(),
         };
 
         ty::TraitDef::new(self.local_def_id(item_id),
                           data.unsafety,
                           data.paren_sugar,
-                          data.has_default_impl,
+                          data.has_auto_impl,
                           self.def_path_table.def_path_hash(item_id))
     }
 
@@ -600,8 +622,11 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
-        self.entry(item_id).generics.unwrap().decode(self)
+    pub fn get_generics(&self,
+                        item_id: DefIndex,
+                        sess: &Session)
+                        -> ty::Generics {
+        self.entry(item_id).generics.unwrap().decode((self, sess))
     }
 
     pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
@@ -729,7 +754,7 @@ impl<'a, 'tcx> CrateMetadata {
                         continue;
                     }
                     EntryKind::Impl(_) |
-                    EntryKind::DefaultImpl(_) => continue,
+                    EntryKind::AutoImpl(_) => continue,
 
                     _ => {}
                 }
@@ -901,7 +926,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
+    pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Rc<[ast::Attribute]> {
         let (node_as, node_index) =
             (node_id.address_space().index(), node_id.as_array_index());
         if self.is_proc_macro(node_id) {
@@ -921,7 +946,7 @@ impl<'a, 'tcx> CrateMetadata {
         if def_key.disambiguated_data.data == DefPathData::StructCtor {
             item = self.entry(def_key.parent.unwrap());
         }
-        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
+        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item, sess));
         let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
         if vec_.len() < node_index + 1 {
             vec_.resize(node_index + 1, None);
@@ -938,9 +963,9 @@ impl<'a, 'tcx> CrateMetadata {
             .collect()
     }
 
-    fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
+    fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec<ast::Attribute> {
         item.attributes
-            .decode(self)
+            .decode((self, sess))
             .map(|mut attr| {
                 // Need new unique IDs: old thread-local IDs won't map to new threads.
                 attr.id = attr::mk_attr_id();
@@ -1006,8 +1031,8 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
 
-    pub fn get_native_libraries(&self) -> Vec<NativeLibrary> {
-        self.root.native_libraries.decode(self).collect()
+    pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
+        self.root.native_libraries.decode((self, sess)).collect()
     }
 
     pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
@@ -1076,9 +1101,9 @@ impl<'a, 'tcx> CrateMetadata {
         self.dllimport_foreign_items.contains(&id)
     }
 
-    pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
+    pub fn is_auto_impl(&self, impl_id: DefIndex) -> bool {
         match self.entry(impl_id).kind {
-            EntryKind::DefaultImpl(_) => true,
+            EntryKind::AutoImpl(_) => true,
             _ => false,
         }
     }
@@ -1183,6 +1208,7 @@ impl<'a, 'tcx> CrateMetadata {
                                       end_pos,
                                       lines,
                                       multibyte_chars,
+                                      non_narrow_chars,
                                       .. } = filemap_to_import;
 
             let source_length = (end_pos - start_pos).to_usize();
@@ -1200,6 +1226,10 @@ impl<'a, 'tcx> CrateMetadata {
             for mbc in &mut multibyte_chars {
                 mbc.pos = mbc.pos - start_pos;
             }
+            let mut non_narrow_chars = non_narrow_chars.into_inner();
+            for swc in &mut non_narrow_chars {
+                *swc = *swc - start_pos;
+            }
 
             let local_version = local_codemap.new_imported_filemap(name,
                                                                    name_was_remapped,
@@ -1207,7 +1237,8 @@ impl<'a, 'tcx> CrateMetadata {
                                                                    src_hash,
                                                                    source_length,
                                                                    lines,
-                                                                   multibyte_chars);
+                                                                   multibyte_chars,
+                                                                   non_narrow_chars);
             debug!("CrateMetaData::imported_filemaps alloc \
                     filemap {:?} original (start_pos {:?} end_pos {:?}) \
                     translated (start_pos {:?} end_pos {:?})",
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index abe2b6d0c1b..d5eee14bf50 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -25,14 +25,13 @@ use rustc::middle::lang_items;
 use rustc::mir;
 use rustc::traits::specialization_graph;
 use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
+use rustc::ty::codec::{self as ty_codec, TyEncoder};
 
 use rustc::session::config::{self, CrateTypeProcMacro};
 use rustc::util::nodemap::{FxHashMap, NodeSet};
 
 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
 
-use std::hash::Hash;
-use std::intrinsics;
 use std::io::prelude::*;
 use std::io::Cursor;
 use std::path::Path;
@@ -119,7 +118,7 @@ impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> {
 
 impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
-        self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
+        ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
     }
 }
 
@@ -127,20 +126,17 @@ impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext
     fn specialized_encode(&mut self,
                           predicates: &ty::GenericPredicates<'tcx>)
                           -> Result<(), Self::Error> {
-        predicates.parent.encode(self)?;
-        predicates.predicates.len().encode(self)?;
-        for predicate in &predicates.predicates {
-            self.encode_with_shorthand(predicate, predicate, |ecx| &mut ecx.predicate_shorthands)?
-        }
-        Ok(())
+        ty_codec::encode_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
     }
 }
 
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-
-    pub fn position(&self) -> usize {
+impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
+    fn position(&self) -> usize {
         self.opaque.position()
     }
+}
+
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R {
         assert_eq!(self.lazy_state, LazyState::NoNode);
@@ -204,44 +200,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         })
     }
 
-    /// Encode the given value or a previously cached shorthand.
-    fn encode_with_shorthand<T, U, M>(&mut self,
-                                      value: &T,
-                                      variant: &U,
-                                      map: M)
-                                      -> Result<(), <Self as Encoder>::Error>
-        where M: for<'b> Fn(&'b mut Self) -> &'b mut FxHashMap<T, usize>,
-              T: Clone + Eq + Hash,
-              U: Encodable
-    {
-        let existing_shorthand = map(self).get(value).cloned();
-        if let Some(shorthand) = existing_shorthand {
-            return self.emit_usize(shorthand);
-        }
-
-        let start = self.position();
-        variant.encode(self)?;
-        let len = self.position() - start;
-
-        // The shorthand encoding uses the same usize as the
-        // discriminant, with an offset so they can't conflict.
-        let discriminant = unsafe { intrinsics::discriminant_value(variant) };
-        assert!(discriminant < SHORTHAND_OFFSET as u64);
-        let shorthand = start + SHORTHAND_OFFSET;
-
-        // Get the number of bits that leb128 could fit
-        // in the same space as the fully encoded type.
-        let leb128_bits = len * 7;
-
-        // Check that the shorthand is a not longer than the
-        // full encoding itself, i.e. it's an obvious win.
-        if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
-            map(self).insert(value.clone(), shorthand);
-        }
-
-        Ok(())
-    }
-
     // Encodes something that corresponds to a single DepNode::GlobalMetaData
     // and registers the Fingerprint in the `metadata_hashes` map.
     pub fn tracked<'x, DATA, R>(&'x mut self,
@@ -626,7 +584,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
-        let variant = tcx.adt_def(adt_def_id).struct_variant();
+        let adt_def = tcx.adt_def(adt_def_id);
+        let variant = adt_def.struct_variant();
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -648,6 +607,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             }
         }
 
+        // If the structure is marked as non_exhaustive then lower the visibility
+        // to within the crate.
+        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+        }
+
         let repr_options = get_repr_options(&tcx, adt_def_id);
 
         Entry {
@@ -961,7 +926,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     ctor_sig: None,
                 }), repr_options)
             }
-            hir::ItemDefaultImpl(..) => {
+            hir::ItemAutoImpl(..) => {
                 let data = ImplData {
                     polarity: hir::ImplPolarity::Positive,
                     defaultness: hir::Defaultness::Final,
@@ -970,7 +935,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
                 };
 
-                EntryKind::DefaultImpl(self.lazy(&data))
+                EntryKind::AutoImpl(self.lazy(&data))
             }
             hir::ItemImpl(_, polarity, defaultness, ..) => {
                 let trait_ref = tcx.impl_trait_ref(def_id);
@@ -1012,7 +977,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 let data = TraitData {
                     unsafety: trait_def.unsafety,
                     paren_sugar: trait_def.paren_sugar,
-                    has_default_impl: tcx.trait_has_default_impl(def_id),
+                    has_auto_impl: tcx.trait_is_auto(def_id),
                     super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
                 };
 
@@ -1559,7 +1524,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
             hir::ItemGlobalAsm(..) |
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTy(..) => {
                 // no sub-item recording needed in these cases
             }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 54dbb68667b..20bdfaea0d0 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -15,7 +15,6 @@
 
 #![feature(box_patterns)]
 #![feature(conservative_impl_trait)]
-#![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![feature(proc_macro_internals)]
 #![feature(quote)]
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 3c3162bcb51..3efe74bfecc 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -54,11 +54,6 @@ pub const METADATA_VERSION: u8 = 4;
 pub const METADATA_HEADER: &'static [u8; 12] =
     &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
-/// The shorthand encoding uses an enum's variant index `usize`
-/// and is offset by this value so it never matches a real variant.
-/// This offset is also chosen so that the first byte is never < 0x80.
-pub const SHORTHAND_OFFSET: usize = 0x80;
-
 /// A value of type T referred to by its absolute position
 /// in the metadata, and which can be decoded lazily.
 ///
@@ -308,7 +303,7 @@ pub enum EntryKind<'tcx> {
     Generator(Lazy<GeneratorData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
-    DefaultImpl(Lazy<ImplData<'tcx>>),
+    AutoImpl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
     AssociatedConst(AssociatedContainer, u8),
@@ -364,7 +359,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for EntryKind<'gcx> {
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
-            EntryKind::DefaultImpl(ref impl_data) |
+            EntryKind::AutoImpl(ref impl_data) |
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -431,14 +426,14 @@ impl_stable_hash_for!(struct VariantData<'tcx> {
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
     pub paren_sugar: bool,
-    pub has_default_impl: bool,
+    pub has_auto_impl: bool,
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
 impl_stable_hash_for!(struct TraitData<'tcx> {
     unsafety,
     paren_sugar,
-    has_default_impl,
+    has_auto_impl,
     super_predicates
 });
 
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index ee2ef00be57..2cb1a23ef5a 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -17,7 +17,8 @@ use rustc::ty::maps::Providers;
 use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local};
 use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
 use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
-use rustc::mir::transform::{MirSource};
+use rustc::mir::transform::MirSource;
+use transform::nll;
 
 use rustc_data_structures::indexed_set::{self, IdxSetBuf};
 use rustc_data_structures::indexed_vec::{Idx};
@@ -46,93 +47,120 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
-    let mir = tcx.mir_validated(def_id);
+    let input_mir = tcx.mir_validated(def_id);
     let src = MirSource::from_local_def_id(tcx, def_id);
     debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id()));
 
-    let mir: &Mir<'tcx> = &mir.borrow();
-    if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.debugging_opts.borrowck_mir {
+    if {
+        !tcx.has_attr(def_id, "rustc_mir_borrowck") &&
+            !tcx.sess.opts.debugging_opts.borrowck_mir &&
+            !tcx.sess.opts.debugging_opts.nll
+    } {
         return;
     }
 
-    let id = src.item_id();
+    tcx.infer_ctxt().enter(|infcx| {
+        let input_mir: &Mir = &input_mir.borrow();
+        do_mir_borrowck(&infcx, input_mir, def_id, src);
+    });
+    debug!("mir_borrowck done");
+}
+
+fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                   input_mir: &Mir<'gcx>,
+                                   def_id: DefId,
+                                   src: MirSource)
+{
+    let tcx = infcx.tcx;
     let attributes = tcx.get_attrs(def_id);
     let param_env = tcx.param_env(def_id);
-    tcx.infer_ctxt().enter(|_infcx| {
-
-        let move_data = match MoveData::gather_moves(mir, tcx, param_env) {
-            Ok(move_data) => move_data,
-            Err((move_data, move_errors)) => {
-                for move_error in move_errors {
-                    let (span, kind): (Span, IllegalMoveOriginKind) = match move_error {
-                        MoveError::UnionMove { .. } =>
-                            unimplemented!("dont know how to report union move errors yet."),
-                        MoveError::IllegalMove { cannot_move_out_of: o } => (o.span, o.kind),
-                    };
-                    let origin = Origin::Mir;
-                    let mut err = match kind {
-                        IllegalMoveOriginKind::Static =>
-                            tcx.cannot_move_out_of(span, "static item", origin),
-                        IllegalMoveOriginKind::BorrowedContent =>
-                            tcx.cannot_move_out_of(span, "borrowed_content", origin),
-                        IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } =>
-                            tcx.cannot_move_out_of_interior_of_drop(span, ty, origin),
-                        IllegalMoveOriginKind::InteriorOfSlice { elem_ty: ty, is_index } =>
-                            tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
-                        IllegalMoveOriginKind::InteriorOfArray { elem_ty: ty, is_index } =>
-                            tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
-                    };
-                    err.emit();
-                }
-                move_data
+
+    let id = src.item_id();
+
+    let move_data: MoveData<'tcx> = match MoveData::gather_moves(input_mir, tcx, param_env) {
+        Ok(move_data) => move_data,
+        Err((move_data, move_errors)) => {
+            for move_error in move_errors {
+                let (span, kind): (Span, IllegalMoveOriginKind) = match move_error {
+                    MoveError::UnionMove { .. } =>
+                        unimplemented!("dont know how to report union move errors yet."),
+                    MoveError::IllegalMove { cannot_move_out_of: o } => (o.span, o.kind),
+                };
+                let origin = Origin::Mir;
+                let mut err = match kind {
+                    IllegalMoveOriginKind::Static =>
+                        tcx.cannot_move_out_of(span, "static item", origin),
+                    IllegalMoveOriginKind::BorrowedContent =>
+                        tcx.cannot_move_out_of(span, "borrowed_content", origin),
+                    IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } =>
+                        tcx.cannot_move_out_of_interior_of_drop(span, ty, origin),
+                    IllegalMoveOriginKind::InteriorOfSlice { elem_ty: ty, is_index } =>
+                        tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
+                    IllegalMoveOriginKind::InteriorOfArray { elem_ty: ty, is_index } =>
+                        tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
+                };
+                err.emit();
             }
-        };
-        let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
-        let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
-        let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
-                                       Borrows::new(tcx, mir),
-                                       |bd, i| bd.location(i));
-        let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
-                                     MaybeInitializedLvals::new(tcx, mir, &mdpe),
-                                     |bd, i| &bd.move_data().move_paths[i]);
-        let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
-                                       MaybeUninitializedLvals::new(tcx, mir, &mdpe),
-                                       |bd, i| &bd.move_data().move_paths[i]);
-
-        let mut mbcx = MirBorrowckCtxt {
-            tcx: tcx,
-            mir: mir,
-            node_id: id,
-            move_data: &mdpe.move_data,
-            param_env: param_env,
-            fake_infer_ctxt: &_infcx,
-        };
+            move_data
+        }
+    };
 
-        let mut state = InProgress::new(flow_borrows,
-                                        flow_inits,
-                                        flow_uninits);
+    // Make our own copy of the MIR. This copy will be modified (in place) to
+    // contain non-lexical lifetimes. It will have a lifetime tied
+    // to the inference context.
+    let mut mir: Mir<'tcx> = input_mir.clone();
+    let mir = &mut mir;
+
+    // If we are in non-lexical mode, compute the non-lexical lifetimes.
+    let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
+        None
+    } else {
+        Some(nll::compute_regions(infcx, src, mir))
+    };
 
-        mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
-    });
+    let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
+    let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+    let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                   Borrows::new(tcx, mir, opt_regioncx.as_ref()),
+                                   |bd, i| bd.location(i));
+    let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                 MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                                 |bd, i| &bd.move_data().move_paths[i]);
+    let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                   MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                                   |bd, i| &bd.move_data().move_paths[i]);
+
+    let mut mbcx = MirBorrowckCtxt {
+        tcx: tcx,
+        mir: mir,
+        node_id: id,
+        move_data: &mdpe.move_data,
+        param_env: param_env,
+        fake_infer_ctxt: &infcx,
+    };
 
-    debug!("mir_borrowck done");
+    let mut state = InProgress::new(flow_borrows,
+                                    flow_inits,
+                                    flow_uninits);
+
+    mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
 }
 
 #[allow(dead_code)]
 pub struct MirBorrowckCtxt<'c, 'b, 'a: 'b+'c, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    mir: &'b Mir<'gcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    mir: &'b Mir<'tcx>,
     node_id: ast::NodeId,
-    move_data: &'b MoveData<'gcx>,
+    move_data: &'b MoveData<'tcx>,
     param_env: ParamEnv<'tcx>,
     fake_infer_ctxt: &'c InferCtxt<'c, 'gcx, 'tcx>,
 }
 
 // (forced to be `pub` due to its use as an associated type below.)
-pub struct InProgress<'b, 'tcx: 'b> {
-    borrows: FlowInProgress<Borrows<'b, 'tcx>>,
-    inits: FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>,
-    uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>,
+pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
+    borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
+    inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
+    uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
 }
 
 struct FlowInProgress<BD> where BD: BitDenotation {
@@ -147,12 +175,12 @@ struct FlowInProgress<BD> where BD: BitDenotation {
 // 2. loans made in overlapping scopes do not conflict
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
-impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'tcx>
     for MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 {
-    type FlowState = InProgress<'b, 'gcx>;
+    type FlowState = InProgress<'b, 'gcx, 'tcx>;
 
-    fn mir(&self) -> &'b Mir<'gcx> { self.mir }
+    fn mir(&self) -> &'b Mir<'tcx> { self.mir }
 
     fn reset_to_entry_of(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) {
         flow_state.each_flow(|b| b.reset_to_entry_of(bb),
@@ -193,7 +221,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
 
     fn visit_statement_entry(&mut self,
                              location: Location,
-                             stmt: &Statement<'gcx>,
+                             stmt: &Statement<'tcx>,
                              flow_state: &Self::FlowState) {
         let summary = flow_state.summary();
         debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {}", location, stmt, summary);
@@ -261,7 +289,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
 
     fn visit_terminator_entry(&mut self,
                               location: Location,
-                              term: &Terminator<'gcx>,
+                              term: &Terminator<'tcx>,
                               flow_state: &Self::FlowState) {
         let loc = location;
         let summary = flow_state.summary();
@@ -336,7 +364,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
             TerminatorKind::Resume |
             TerminatorKind::Return |
             TerminatorKind::GeneratorDrop |
-            TerminatorKind::Unreachable => {
+            TerminatorKind::Unreachable |
+            TerminatorKind::FalseEdges { .. } => {
                 // no data used, thus irrelevant to borrowck
             }
         }
@@ -405,9 +434,9 @@ enum WriteKind {
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
     fn access_lvalue(&mut self,
                      context: Context,
-                     lvalue_span: (&Lvalue<'gcx>, Span),
+                     lvalue_span: (&Lvalue<'tcx>, Span),
                      kind: (ShallowOrDeep, ReadOrWrite),
-                     flow_state: &InProgress<'b, 'gcx>) {
+                     flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         // FIXME: also need to check permissions (e.g. reject mut
         // borrow of immutable ref, moves through non-`Box`-ref)
         let (sd, rw) = kind;
@@ -425,8 +454,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                                     context, lvalue_span, borrow),
                             ReadKind::Borrow(bk) => {
                                 let end_issued_loan_span =
-                                    flow_state.borrows.base_results.operator().region_span(
-                                        &borrow.region).end_point();
+                                    flow_state.borrows.base_results.operator().opt_region_end_span(
+                                        &borrow.region);
                                 this.report_conflicting_borrow(
                                     context, common_prefix, lvalue_span, bk,
                                     &borrow, end_issued_loan_span)
@@ -438,8 +467,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                         match kind {
                             WriteKind::MutableBorrow(bk) => {
                                 let end_issued_loan_span =
-                                    flow_state.borrows.base_results.operator().region_span(
-                                        &borrow.region).end_point();
+                                    flow_state.borrows.base_results.operator().opt_region_end_span(
+                                        &borrow.region);
                                 this.report_conflicting_borrow(
                                     context, common_prefix, lvalue_span, bk,
                                     &borrow, end_issued_loan_span)
@@ -460,10 +489,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 
     fn mutate_lvalue(&mut self,
                      context: Context,
-                     lvalue_span: (&Lvalue<'gcx>, Span),
+                     lvalue_span: (&Lvalue<'tcx>, Span),
                      kind: ShallowOrDeep,
                      mode: MutateMode,
-                     flow_state: &InProgress<'b, 'gcx>) {
+                     flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd.
         match mode {
             MutateMode::WriteAndRead => {
@@ -482,9 +511,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 
     fn consume_rvalue(&mut self,
                       context: Context,
-                      (rvalue, span): (&Rvalue<'gcx>, Span),
+                      (rvalue, span): (&Rvalue<'tcx>, Span),
                       _location: Location,
-                      flow_state: &InProgress<'b, 'gcx>) {
+                      flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         match *rvalue {
             Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => {
                 let access_kind = match bk {
@@ -540,8 +569,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     fn consume_operand(&mut self,
                        context: Context,
                        consume_via_drop: ConsumeKind,
-                       (operand, span): (&Operand<'gcx>, Span),
-                       flow_state: &InProgress<'b, 'gcx>) {
+                       (operand, span): (&Operand<'tcx>, Span),
+                       flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         match *operand {
             Operand::Consume(ref lvalue) => {
                 self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state)
@@ -553,8 +582,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     fn consume_lvalue(&mut self,
                       context: Context,
                       consume_via_drop: ConsumeKind,
-                      lvalue_span: (&Lvalue<'gcx>, Span),
-                      flow_state: &InProgress<'b, 'gcx>) {
+                      lvalue_span: (&Lvalue<'tcx>, Span),
+                      flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         let lvalue = lvalue_span.0;
         let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
         let moves_by_default =
@@ -584,8 +613,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
     fn check_if_reassignment_to_immutable_state(&mut self,
                                                 context: Context,
-                                                (lvalue, span): (&Lvalue<'gcx>, Span),
-                                                flow_state: &InProgress<'b, 'gcx>) {
+                                                (lvalue, span): (&Lvalue<'tcx>, Span),
+                                                flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         let move_data = self.move_data;
 
         // determine if this path has a non-mut owner (and thus needs checking).
@@ -635,8 +664,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     fn check_if_path_is_moved(&mut self,
                               context: Context,
                               desired_action: &str,
-                              lvalue_span: (&Lvalue<'gcx>, Span),
-                              flow_state: &InProgress<'b, 'gcx>) {
+                              lvalue_span: (&Lvalue<'tcx>, Span),
+                              flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         // FIXME: analogous code in check_loans first maps `lvalue` to
         // its base_path ... but is that what we want here?
         let lvalue = self.base_path(lvalue_span.0);
@@ -725,7 +754,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     /// An Err result includes a tag indicated why the search failed.
     /// Currenly this can only occur if the lvalue is built off of a
     /// static variable, as we do not track those in the MoveData.
-    fn move_path_closest_to(&mut self, lvalue: &Lvalue<'gcx>)
+    fn move_path_closest_to(&mut self, lvalue: &Lvalue<'tcx>)
                             -> Result<MovePathIndex, NoMovePathFound>
     {
         let mut last_prefix = lvalue;
@@ -743,7 +772,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     }
 
     fn move_path_for_lvalue(&mut self,
-                            lvalue: &Lvalue<'gcx>)
+                            lvalue: &Lvalue<'tcx>)
                             -> Option<MovePathIndex>
     {
         // If returns None, then there is no move path corresponding
@@ -758,8 +787,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 
     fn check_if_assigned_path_is_moved(&mut self,
                                        context: Context,
-                                       (lvalue, span): (&Lvalue<'gcx>, Span),
-                                       flow_state: &InProgress<'b, 'gcx>) {
+                                       (lvalue, span): (&Lvalue<'tcx>, Span),
+                                       flow_state: &InProgress<'b, 'gcx, 'tcx>) {
         // recur down lvalue; dispatch to check_if_path_is_moved when necessary
         let mut lvalue = lvalue;
         loop {
@@ -827,10 +856,10 @@ enum NoMovePathFound {
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
     fn each_borrow_involving_path<F>(&mut self,
                                      _context: Context,
-                                     access_lvalue: (ShallowOrDeep, &Lvalue<'gcx>),
-                                     flow_state: &InProgress<'b, 'gcx>,
+                                     access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
+                                     flow_state: &InProgress<'b, 'gcx, 'tcx>,
                                      mut op: F)
-        where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>, &Lvalue) -> Control
+        where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue) -> Control
     {
         let (access, lvalue) = access_lvalue;
 
@@ -928,9 +957,9 @@ mod prefixes {
     }
 
 
-    pub(super) struct Prefixes<'c, 'tcx: 'c> {
+    pub(super) struct Prefixes<'c, 'gcx: 'tcx, 'tcx: 'c> {
         mir: &'c Mir<'tcx>,
-        tcx: TyCtxt<'c, 'tcx, 'tcx>,
+        tcx: TyCtxt<'c, 'gcx, 'tcx>,
         kind: PrefixSet,
         next: Option<&'c Lvalue<'tcx>>,
     }
@@ -951,15 +980,15 @@ mod prefixes {
         /// (inclusive) from longest to smallest, potentially
         /// terminating the iteration early based on `kind`.
         pub(super) fn prefixes<'d>(&self,
-                                   lvalue: &'d Lvalue<'gcx>,
+                                   lvalue: &'d Lvalue<'tcx>,
                                    kind: PrefixSet)
-                                   -> Prefixes<'d, 'gcx> where 'b: 'd
+                                   -> Prefixes<'d, 'gcx, 'tcx> where 'b: 'd
         {
             Prefixes { next: Some(lvalue), kind, mir: self.mir, tcx: self.tcx }
         }
     }
 
-    impl<'c, 'tcx> Iterator for Prefixes<'c, 'tcx> {
+    impl<'c, 'gcx, 'tcx> Iterator for Prefixes<'c, 'gcx, 'tcx> {
         type Item = &'c Lvalue<'tcx>;
         fn next(&mut self) -> Option<Self::Item> {
             let mut cursor = match self.next {
@@ -1101,7 +1130,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                                  (lvalue, span): (&Lvalue, Span),
                                  gen_borrow_kind: BorrowKind,
                                  issued_borrow: &BorrowData,
-                                 end_issued_loan_span: Span) {
+                                 end_issued_loan_span: Option<Span>) {
         use self::prefixes::IsPrefixOf;
 
         assert!(common_prefix.is_prefix_of(lvalue));
@@ -1315,7 +1344,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     // moves out of a Box. They should be removed when/if we stop
     // treating Box specially (e.g. when/if DerefMove is added...)
 
-    fn base_path<'d>(&self, lvalue: &'d Lvalue<'gcx>) -> &'d Lvalue<'gcx> {
+    fn base_path<'d>(&self, lvalue: &'d Lvalue<'tcx>) -> &'d Lvalue<'tcx> {
         //! Returns the base of the leftmost (deepest) dereference of an
         //! Box in `lvalue`. If there is no dereference of an Box
         //! in `lvalue`, then it just returns `lvalue` itself.
@@ -1364,10 +1393,10 @@ impl ContextKind {
     fn new(self, loc: Location) -> Context { Context { kind: self, loc: loc } }
 }
 
-impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> {
-    pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'tcx>>,
-                      inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
-                      uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>)
+impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
+    pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
+                      inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
+                      uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>)
                       -> Self {
         InProgress {
             borrows: FlowInProgress::new(borrows),
@@ -1380,9 +1409,9 @@ impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> {
                              mut xform_borrows: XB,
                              mut xform_inits: XI,
                              mut xform_uninits: XU) where
-        XB: FnMut(&mut FlowInProgress<Borrows<'b, 'tcx>>),
-        XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>),
-        XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>),
+        XB: FnMut(&mut FlowInProgress<Borrows<'b, 'gcx, 'tcx>>),
+        XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>),
+        XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>),
     {
         xform_borrows(&mut self.borrows);
         xform_inits(&mut self.inits);
@@ -1438,7 +1467,7 @@ impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> {
     }
 }
 
-impl<'b, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>> {
+impl<'b, 'gcx, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>> {
     fn has_any_child_of(&self, mpi: MovePathIndex) -> Option<MovePathIndex> {
         let move_data = self.base_results.operator().move_data();
 
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 56c926eaa61..b65d859e7d7 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -21,7 +21,7 @@ use rustc::mir::*;
 use rustc::hir;
 use hair::*;
 use syntax::ast::{Name, NodeId};
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::Span;
 
 // helper functions, broken out by category:
 mod simplify;
@@ -54,11 +54,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             (body, scope.unwrap_or(self.visibility_scope))
         }).collect();
 
+        // create binding start block for link them by false edges
+        let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len());
+        let pre_binding_blocks: Vec<_> = (0..candidate_count + 1)
+            .map(|_| self.cfg.start_new_block()).collect();
+
         // assemble a list of candidates: there is one candidate per
         // pattern, which means there may be more than one candidate
         // *per arm*. These candidates are kept sorted such that the
         // highest priority candidate comes first in the list.
         // (i.e. same order as in source)
+
         let candidates: Vec<_> =
             arms.iter()
                 .enumerate()
@@ -66,17 +72,25 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     arm.patterns.iter()
                                 .map(move |pat| (arm_index, pat, arm.guard.clone()))
                 })
-                .map(|(arm_index, pattern, guard)| {
+                .zip(pre_binding_blocks.iter().zip(pre_binding_blocks.iter().skip(1)))
+                .map(|((arm_index, pattern, guard),
+                       (pre_binding_block, next_candidate_pre_binding_block))| {
                     Candidate {
                         span: pattern.span,
                         match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
                         bindings: vec![],
                         guard,
                         arm_index,
+                        pre_binding_block: *pre_binding_block,
+                        next_candidate_pre_binding_block: *next_candidate_pre_binding_block,
                     }
                 })
                 .collect();
 
+        let outer_source_info = self.source_info(span);
+        self.cfg.terminate(*pre_binding_blocks.last().unwrap(),
+                           outer_source_info, TerminatorKind::Unreachable);
+
         // this will generate code to test discriminant_lvalue and
         // branch to the appropriate arm block
         let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
@@ -148,7 +162,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
             bindings: vec![],
             guard: None,
-            arm_index: 0, // since we don't call `match_candidates`, this field is unused
+
+            // since we don't call `match_candidates`, next fields is unused
+            arm_index: 0,
+            pre_binding_block: block,
+            next_candidate_pre_binding_block: block
         };
 
         // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -278,6 +296,10 @@ pub struct Candidate<'pat, 'tcx:'pat> {
 
     // ...and then we branch to arm with this index.
     arm_index: usize,
+
+    // ...and the blocks for add false edges between candidates
+    pre_binding_block: BasicBlock,
+    next_candidate_pre_binding_block: BasicBlock,
 }
 
 #[derive(Clone, Debug)]
@@ -398,17 +420,43 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
         debug!("match_candidates: {:?} candidates fully matched", fully_matched);
         let mut unmatched_candidates = candidates.split_off(fully_matched);
-        for (index, candidate) in candidates.into_iter().enumerate() {
+
+        let fully_matched_with_guard =
+            candidates.iter().take_while(|c| c.guard.is_some()).count();
+
+        let unreachable_candidates = if fully_matched_with_guard + 1 < candidates.len() {
+            candidates.split_off(fully_matched_with_guard + 1)
+        } else {
+            vec![]
+        };
+
+        for candidate in candidates {
             // If so, apply any bindings, test the guard (if any), and
             // branch to the arm.
-            let is_last = index == fully_matched - 1;
-            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks,
-                                                                   candidate, is_last) {
+            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
                 block = b;
             } else {
                 // if None is returned, then any remaining candidates
                 // are unreachable (at least not through this path).
-                return vec![];
+                // Link them with false edges.
+                debug!("match_candidates: add false edges for unreachable {:?} and unmatched {:?}",
+                       unreachable_candidates, unmatched_candidates);
+                for candidate in unreachable_candidates {
+                    let source_info = self.source_info(candidate.span);
+                    let target = self.cfg.start_new_block();
+                    if let Some(otherwise) = self.bind_and_guard_matched_candidate(target,
+                                                                                   arm_blocks,
+                                                                                   candidate) {
+                        self.cfg.terminate(otherwise, source_info, TerminatorKind::Unreachable);
+                    }
+                }
+
+                if unmatched_candidates.is_empty() {
+                    return vec![]
+                } else {
+                    let target = self.cfg.start_new_block();
+                    return self.match_candidates(span, arm_blocks, unmatched_candidates, target);
+                }
             }
         }
 
@@ -423,9 +471,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             self.test_candidates(span, arm_blocks, &unmatched_candidates, block);
 
         // If the target candidates were exhaustive, then we are done.
-        if otherwise.is_empty() {
-            return vec![];
-        }
+        // But for borrowck continue build decision tree.
 
         // If all candidates were sorted into `target_candidates` somewhere, then
         // the initial set was inexhaustive.
@@ -666,17 +712,27 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     fn bind_and_guard_matched_candidate<'pat>(&mut self,
                                               mut block: BasicBlock,
                                               arm_blocks: &mut ArmBlocks,
-                                              candidate: Candidate<'pat, 'tcx>,
-                                              is_last_arm: bool)
+                                              candidate: Candidate<'pat, 'tcx>)
                                               -> Option<BasicBlock> {
         debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
                block, candidate);
 
         debug_assert!(candidate.match_pairs.is_empty());
 
-        self.bind_matched_candidate(block, candidate.bindings);
-
         let arm_block = arm_blocks.blocks[candidate.arm_index];
+        let candidate_source_info = self.source_info(candidate.span);
+
+        self.cfg.terminate(block, candidate_source_info,
+                               TerminatorKind::Goto { target: candidate.pre_binding_block });
+
+        block = self.cfg.start_new_block();
+        self.cfg.terminate(candidate.pre_binding_block, candidate_source_info,
+                               TerminatorKind::FalseEdges {
+                                   real_target: block,
+                                   imaginary_targets:
+                                       vec![candidate.next_candidate_pre_binding_block]});
+
+        self.bind_matched_candidate(block, candidate.bindings);
 
         if let Some(guard) = candidate.guard {
             // the block to branch to if the guard fails; if there is no
@@ -684,30 +740,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let guard = self.hir.mirror(guard);
             let source_info = self.source_info(guard.span);
             let cond = unpack!(block = self.as_local_operand(block, guard));
-            let otherwise = self.cfg.start_new_block();
+
+            let false_edge_block = self.cfg.start_new_block();
             self.cfg.terminate(block, source_info,
-                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
-            Some(otherwise)
-        } else if !is_last_arm {
-            // Add always true guard in case of more than one arm
-            // it creates false edges and allow MIR borrowck detects errors
-            // FIXME(#45184) -- permit "false edges"
-            let source_info = self.source_info(candidate.span);
-            let true_expr = Expr {
-                temp_lifetime: None,
-                ty: self.hir.tcx().types.bool,
-                span: DUMMY_SP,
-                kind: ExprKind::Literal{literal: self.hir.true_literal()},
-            };
-            let cond = unpack!(block = self.as_local_operand(block, true_expr));
+                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block,
+                                   false_edge_block));
+
             let otherwise = self.cfg.start_new_block();
-            self.cfg.terminate(block, source_info,
-                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
+            self.cfg.terminate(false_edge_block, source_info,
+                               TerminatorKind::FalseEdges {
+                                   real_target: otherwise,
+                                   imaginary_targets:
+                                       vec![candidate.next_candidate_pre_binding_block] });
             Some(otherwise)
         } else {
-            let source_info = self.source_info(candidate.span);
-            self.cfg.terminate(block, source_info,
-                               TerminatorKind::Goto { target: arm_block  });
+            self.cfg.terminate(block, candidate_source_info,
+                               TerminatorKind::Goto { target: arm_block });
             None
         }
     }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 7b91c43aa37..4792bf2b213 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -598,6 +598,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             bindings: candidate.bindings.clone(),
             guard: candidate.guard.clone(),
             arm_index: candidate.arm_index,
+            pre_binding_block: candidate.pre_binding_block,
+            next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
         }
     }
 
@@ -659,6 +661,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             bindings: candidate.bindings.clone(),
             guard: candidate.guard.clone(),
             arm_index: candidate.arm_index,
+            pre_binding_block: candidate.pre_binding_block,
+            next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
         }
     }
 
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index b2f0ff57b62..2073d495300 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
-use rustc::mir::visit::{MutVisitor, Lookup};
+use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
@@ -165,7 +165,7 @@ struct GlobalizeMir<'a, 'gcx: 'a> {
 }
 
 impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         if let Some(lifted) = self.tcx.lift(ty) {
             *ty = lifted;
         } else {
@@ -240,10 +240,10 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
-pub fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             closure_expr_id: ast::NodeId,
-                             body_id: hir::BodyId)
-                             -> Ty<'tcx> {
+pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                       closure_expr_id: ast::NodeId,
+                                       body_id: hir::BodyId)
+                                       -> Ty<'tcx> {
     let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
     let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
 
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index bd41bce67da..e35bd34c40b 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -58,9 +58,9 @@ pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
 /// is no need to maintain separate drop flags to track such state.
 ///
 /// FIXME: we have to do something for moving slice patterns.
-fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                      mir: &Mir<'tcx>,
-                                                      lv: &mir::Lvalue<'tcx>) -> bool {
+fn lvalue_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                                            mir: &Mir<'tcx>,
+                                                            lv: &mir::Lvalue<'tcx>) -> bool {
     let ty = lv.ty(mir, tcx).to_ty(tcx);
     match ty.sty {
         ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
@@ -79,8 +79,8 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
     }
 }
 
-pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_lookup_result_bits<'a, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
     lookup_result: LookupResult,
@@ -97,16 +97,16 @@ pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>(
     }
 }
 
-pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
     move_path_index: MovePathIndex,
     mut each_child: F)
     where F: FnMut(MovePathIndex)
 {
-    fn is_terminal_path<'a, 'tcx>(
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn is_terminal_path<'a, 'gcx, 'tcx>(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
         move_data: &MoveData<'tcx>,
         path: MovePathIndex) -> bool
@@ -115,8 +115,8 @@ pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
             tcx, mir, &move_data.move_paths[path].lvalue)
     }
 
-    fn on_all_children_bits<'a, 'tcx, F>(
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
         mir: &Mir<'tcx>,
         move_data: &MoveData<'tcx>,
         move_path_index: MovePathIndex,
@@ -138,10 +138,10 @@ pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
     on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child);
 }
 
-pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
-    ctxt: &MoveDataParamEnv<'tcx>,
+    ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     path: MovePathIndex,
     mut each_child: F)
     where F: FnMut(MovePathIndex)
@@ -151,7 +151,9 @@ pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
         let ty = lvalue.ty(mir, tcx).to_ty(tcx);
         debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
 
-        if ty.needs_drop(tcx, ctxt.param_env) {
+        let gcx = tcx.global_tcx();
+        let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
+        if erased_ty.needs_drop(gcx, ctxt.param_env) {
             each_child(child);
         } else {
             debug!("on_all_drop_children_bits - skipping")
@@ -159,10 +161,10 @@ pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
     })
 }
 
-pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
-    ctxt: &MoveDataParamEnv<'tcx>,
+    ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     mut callback: F)
     where F: FnMut(MovePathIndex, DropFlagState)
 {
@@ -176,10 +178,10 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     }
 }
 
-pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn drop_flag_effects_for_location<'a, 'gcx, 'tcx, F>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &Mir<'tcx>,
-    ctxt: &MoveDataParamEnv<'tcx>,
+    ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
     loc: Location,
     mut callback: F)
     where F: FnMut(MovePathIndex, DropFlagState)
@@ -196,7 +198,9 @@ pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
         // don't move out of non-Copy things
         let lvalue = &move_data.move_paths[path].lvalue;
         let ty = lvalue.ty(mir, tcx).to_ty(tcx);
-        if !ty.moves_by_default(tcx, param_env, DUMMY_SP) {
+        let gcx = tcx.global_tcx();
+        let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
+        if !erased_ty.moves_by_default(gcx, param_env, DUMMY_SP) {
             continue;
         }
 
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 9321121fe15..e8bf543b70b 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -21,6 +21,8 @@ use rustc_data_structures::indexed_vec::{IndexVec};
 
 use dataflow::{BitDenotation, BlockSets, DataflowOperator};
 pub use dataflow::indexes::BorrowIndex;
+use transform::nll::region_infer::RegionInferenceContext;
+use transform::nll::ToRegionIndex;
 
 use syntax_pos::Span;
 
@@ -29,13 +31,14 @@ use std::fmt;
 // `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
 // uniquely identified in the MIR by the `Location` of the assigment
 // statement in which it appears on the right hand side.
-pub struct Borrows<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
     borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
     region_span_map: FxHashMap<RegionKind, Span>,
+    nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>,
 }
 
 // temporarily allow some dead fields: `kind` and `region` will be
@@ -63,8 +66,11 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
     }
 }
 
-impl<'a, 'tcx> Borrows<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               nonlexical_regioncx: Option<&'a RegionInferenceContext<'tcx>>)
+               -> Self {
         let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
                                           location_map: FxHashMap(),
                                           region_map: FxHashMap(),
@@ -75,7 +81,8 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
                          borrows: visitor.idx_vec,
                          location_map: visitor.location_map,
                          region_map: visitor.region_map,
-                         region_span_map: visitor.region_span_map};
+                         region_span_map: visitor.region_span_map,
+                         nonlexical_regioncx };
 
         struct GatherBorrows<'tcx> {
             idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
@@ -116,14 +123,44 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
         &self.borrows[idx].location
     }
 
-    pub fn region_span(&self, region: &Region) -> Span {
+    /// Returns the span for the "end point" given region. This will
+    /// return `None` if NLL is enabled, since that concept has no
+    /// meaning there.  Otherwise, it should return some.
+    pub fn opt_region_end_span(&self, region: &Region) -> Option<Span> {
         let opt_span = self.region_span_map.get(region);
-        assert!(opt_span.is_some(), "end region not found for {:?}", region);
-        *opt_span.unwrap()
+        assert!(self.nonlexical_regioncx.is_some() ||
+                opt_span.is_some(), "end region not found for {:?}", region);
+        opt_span.map(|s| s.end_point())
+    }
+
+    /// Add all borrows to the kill set, if those borrows are out of scope at `location`.
+    fn kill_loans_out_of_scope_at_location(&self,
+                                           sets: &mut BlockSets<BorrowIndex>,
+                                           location: Location) {
+        if let Some(regioncx) = self.nonlexical_regioncx {
+            for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
+                let borrow_region = borrow_data.region.to_region_index();
+                if !regioncx.region_contains_point(borrow_region, location) {
+                    // The region checker really considers the borrow
+                    // to start at the point **after** the location of
+                    // the borrow, but the borrow checker puts the gen
+                    // directly **on** the location of the
+                    // borrow. This results in a gen/kill both being
+                    // generated for same point if we are not
+                    // careful. Probably we should change the point of
+                    // the gen, but for now we hackily account for the
+                    // mismatch here by not generating a kill for the
+                    // location on the borrow itself.
+                    if location != borrow_data.location {
+                        sets.kill(&borrow_index);
+                    }
+                }
+            }
+        }
     }
 }
 
-impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
     type Idx = BorrowIndex;
     fn name() -> &'static str { "borrows" }
     fn bits_per_block(&self) -> usize {
@@ -146,6 +183,7 @@ impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
         match stmt.kind {
             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); }
                 } else {
                     // (if there is no entry, then there are no borrows to be tracked)
@@ -172,11 +210,14 @@ impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
             mir::StatementKind::Nop => {}
 
         }
+
+        self.kill_loans_out_of_scope_at_location(sets, location);
     }
+
     fn terminator_effect(&self,
-                         _sets: &mut BlockSets<BorrowIndex>,
-                         _location: Location) {
-        // no terminators start nor end region scopes.
+                         sets: &mut BlockSets<BorrowIndex>,
+                         location: Location) {
+        self.kill_loans_out_of_scope_at_location(sets, location);
     }
 
     fn propagate_call_return(&self,
@@ -188,14 +229,14 @@ impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
         pred1 | pred2 // union effects of preds when computing borrows
     }
 }
 
-impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
         false // bottom = no Rvalue::Refs are active by default
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 19a595622b9..af99706be81 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -69,23 +69,23 @@ pub(super) mod borrows;
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeUninitializedLvals` yields the set of
 /// l-values that would require a dynamic drop-flag at that statement.
-pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct MaybeInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               mdpe: &'a MoveDataParamEnv<'tcx>)
+               mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
         MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
@@ -124,23 +124,23 @@ impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeInitializedLvals` yields the set of
 /// l-values that would require a dynamic drop-flag at that statement.
-pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct MaybeUninitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               mdpe: &'a MoveDataParamEnv<'tcx>)
+               mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
         MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
@@ -185,27 +185,27 @@ impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
 /// Similarly, at a given `drop` statement, the set-difference between
 /// this data and `MaybeInitializedLvals` yields the set of l-values
 /// that would require a dynamic drop-flag at that statement.
-pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct DefinitelyInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               mdpe: &'a MoveDataParamEnv<'tcx>)
+               mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
                -> Self
     {
         DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
-impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
@@ -216,7 +216,7 @@ impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
     fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
@@ -227,7 +227,7 @@ impl<'a, 'tcx> MaybeUninitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
     fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
     {
@@ -238,7 +238,7 @@ impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     type Idx = MovePathIndex;
     fn name() -> &'static str { "maybe_init" }
     fn bits_per_block(&self) -> usize {
@@ -290,7 +290,7 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
     type Idx = MovePathIndex;
     fn name() -> &'static str { "maybe_uninit" }
     fn bits_per_block(&self) -> usize {
@@ -345,7 +345,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
     type Idx = MovePathIndex;
     fn name() -> &'static str { "definite_init" }
     fn bits_per_block(&self) -> usize {
@@ -399,21 +399,21 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
 
-impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
         pred1 & pred2 // "definitely" means we intersect effects of both preds
@@ -430,21 +430,21 @@ impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> {
 // propagating, or you start at all-ones and then use Intersect as
 // your merge when propagating.
 
-impl<'a, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
         false // bottom = uninitialized
     }
 }
 
-impl<'a, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
         false // bottom = initialized (start_block_effect counters this at outset)
     }
 }
 
-impl<'a, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
         true // bottom = initialized (start_block_effect counters this at outset)
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 9fa5691d647..f5517096e3a 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -91,19 +91,19 @@ pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option
     return None;
 }
 
-pub struct MoveDataParamEnv<'tcx> {
+pub struct MoveDataParamEnv<'gcx, 'tcx> {
     pub(crate) move_data: MoveData<'tcx>,
-    pub(crate) param_env: ty::ParamEnv<'tcx>,
+    pub(crate) param_env: ty::ParamEnv<'gcx>,
 }
 
-pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                mir: &Mir<'tcx>,
-                                node_id: ast::NodeId,
-                                attributes: &[ast::Attribute],
-                                dead_unwinds: &IdxSet<BasicBlock>,
-                                bd: BD,
-                                p: P)
-                                -> DataflowResults<BD>
+pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                                 mir: &Mir<'tcx>,
+                                                 node_id: ast::NodeId,
+                                                 attributes: &[ast::Attribute],
+                                                 dead_unwinds: &IdxSet<BasicBlock>,
+                                                 bd: BD,
+                                                 p: P)
+                                                 -> DataflowResults<BD>
     where BD: BitDenotation,
           P: Fn(&BD, BD::Idx) -> &fmt::Debug
 {
@@ -612,9 +612,9 @@ pub trait BitDenotation: DataflowOperator {
                              dest_lval: &mir::Lvalue);
 }
 
-impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
+impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
 {
-    pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pub fn new(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
                mir: &'a Mir<'tcx>,
                dead_unwinds: &'a IdxSet<mir::BasicBlock>,
                denotation: D) -> Self {
@@ -721,6 +721,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
                     self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
                 }
             }
+            mir::TerminatorKind::FalseEdges { ref real_target, ref imaginary_targets } => {
+                self.propagate_bits_into_entry_set_for(in_out, changed, real_target);
+                for target in imaginary_targets {
+                    self.propagate_bits_into_entry_set_for(in_out, changed, target);
+                }
+            }
         }
     }
 
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 0790d937ceb..79ea745125c 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -25,18 +25,18 @@ use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, Move
 use super::{MoveError};
 use super::IllegalMoveOriginKind::*;
 
-struct MoveDataBuilder<'a, 'tcx: 'a> {
+struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    param_env: ty::ParamEnv<'gcx>,
     data: MoveData<'tcx>,
     errors: Vec<MoveError<'tcx>>,
 }
 
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
     fn new(mir: &'a Mir<'tcx>,
-           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: ty::ParamEnv<'tcx>)
+           tcx: TyCtxt<'a, 'gcx, 'tcx>,
+           param_env: ty::ParamEnv<'gcx>)
            -> Self {
         let mut move_paths = IndexVec::new();
         let mut path_map = IndexVec::new();
@@ -86,7 +86,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     }
 }
 
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
     /// This creates a MovePath for a given lvalue, returning an `MovePathError`
     /// if that lvalue can't be moved from.
     ///
@@ -175,7 +175,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
     fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
         debug!("{}", {
             debug!("moves for {:?}:", self.mir.span);
@@ -197,11 +197,11 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     }
 }
 
-pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
-                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     param_env: ty::ParamEnv<'tcx>)
-                                     -> Result<MoveData<'tcx>,
-                                               (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+pub(super) fn gather_moves<'a, 'gcx, 'tcx>(mir: &Mir<'tcx>,
+                                           tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                           param_env: ty::ParamEnv<'gcx>)
+                                           -> Result<MoveData<'tcx>,
+                                                     (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
     let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
 
     for (bb, block) in mir.basic_blocks().iter_enumerated() {
@@ -220,7 +220,7 @@ pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
     builder.finalize()
 }
 
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
     fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
         debug!("gather_statement({:?}, {:?})", loc, stmt);
         (Gatherer { builder: self, loc }).gather_statement(stmt);
@@ -232,12 +232,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
     }
 }
 
-struct Gatherer<'b, 'a: 'b, 'tcx: 'a> {
-    builder: &'b mut MoveDataBuilder<'a, 'tcx>,
+struct Gatherer<'b, 'a: 'b, 'gcx: 'tcx, 'tcx: 'a> {
+    builder: &'b mut MoveDataBuilder<'a, 'gcx, 'tcx>,
     loc: Location,
 }
 
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
     fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
         match stmt.kind {
             StatementKind::Assign(ref lval, ref rval) => {
@@ -305,6 +305,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             TerminatorKind::Goto { target: _ } |
             TerminatorKind::Resume |
             TerminatorKind::GeneratorDrop |
+            TerminatorKind::FalseEdges { .. } |
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
@@ -352,8 +353,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         debug!("gather_move({:?}, {:?})", self.loc, lval);
 
         let tcx = self.builder.tcx;
+        let gcx = tcx.global_tcx();
         let lv_ty = lval.ty(self.builder.mir, tcx).to_ty(tcx);
-        if !lv_ty.moves_by_default(tcx, self.builder.param_env, DUMMY_SP) {
+        let erased_ty = gcx.lift(&tcx.erase_regions(&lv_ty)).unwrap();
+        if !erased_ty.moves_by_default(gcx, self.builder.param_env, DUMMY_SP) {
             debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", self.loc, lval, lv_ty);
             return
         }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 9369156a223..5bfecd01aaa 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -256,10 +256,10 @@ impl<'tcx> MoveError<'tcx> {
     }
 }
 
-impl<'a, 'tcx> MoveData<'tcx> {
+impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
     pub fn gather_moves(mir: &Mir<'tcx>,
-                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: ty::ParamEnv<'tcx>)
+                        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                        param_env: ty::ParamEnv<'gcx>)
                         -> Result<Self, (Self, Vec<MoveError<'tcx>>)> {
         builder::gather_moves(mir, tcx, param_env)
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 7e4206e14c5..b72823dff2b 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -18,13 +18,14 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(conservative_impl_trait)]
 #![feature(const_fn)]
-#![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(placement_in_syntax)]
 #![feature(collection_placement)]
 #![feature(nonzero)]
+#![feature(underscore_lifetimes)]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 49ce3622399..80c8f22c102 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -73,7 +73,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Resume |
             TerminatorKind::Return |
-            TerminatorKind::Unreachable => {
+            TerminatorKind::Unreachable |
+            TerminatorKind::FalseEdges { .. } => {
                                 // safe (at least as emitted during MIR construction)
             }
 
diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs
index a6750f400ba..d356d3b5a85 100644
--- a/src/librustc_mir/transform/clean_end_regions.rs
+++ b/src/librustc_mir/transform/clean_end_regions.rs
@@ -24,7 +24,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc::middle::region;
 use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
-use rustc::mir::visit::{MutVisitor, Visitor, Lookup};
+use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
 use rustc::ty::{Ty, RegionKind, TyCtxt};
 
 pub struct CleanEndRegions;
@@ -67,7 +67,7 @@ impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_ty(&mut self, ty: &Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
         // Gather regions that occur in types
         for re in ty.walk().flat_map(|t| t.regions()) {
             match *re {
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index be1b794ecdf..94da1f31a96 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -83,7 +83,7 @@ fn find_dead_unwinds<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     id: ast::NodeId,
-    env: &MoveDataParamEnv<'tcx>)
+    env: &MoveDataParamEnv<'tcx, 'tcx>)
     -> IdxSetBuf<BasicBlock>
 {
     debug!("find_dead_unwinds({:?})", mir.span);
@@ -146,7 +146,7 @@ impl InitializationData {
     fn apply_location<'a,'tcx>(&mut self,
                                tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                mir: &Mir<'tcx>,
-                               env: &MoveDataParamEnv<'tcx>,
+                               env: &MoveDataParamEnv<'tcx, 'tcx>,
                                loc: Location)
     {
         drop_flag_effects_for_location(tcx, mir, env, loc, |path, df| {
@@ -280,9 +280,9 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
 struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
-    env: &'a MoveDataParamEnv<'tcx>,
-    flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>,
-    flow_uninits:  DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>,
+    env: &'a MoveDataParamEnv<'tcx, 'tcx>,
+    flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx, 'tcx>>,
+    flow_uninits:  DataflowResults<MaybeUninitializedLvals<'a, 'tcx, 'tcx>>,
     drop_flags: FxHashMap<MovePathIndex, Local>,
     patch: MirPatch<'tcx>,
 }
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index dc18cdd8f0d..08ca20e50eb 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -17,7 +17,7 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::mir::*;
-use rustc::mir::visit::{MutVisitor, Lookup};
+use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::mir::transform::{MirPass, MirSource};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
@@ -35,7 +35,7 @@ impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: Lookup) {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         if !self.in_validation_statement {
             *ty = self.tcx.erase_regions(ty);
         }
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 7d0814b67fb..52a50333f45 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -68,7 +68,7 @@ use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
 use rustc::ty::subst::{Kind, Substs};
 use util::dump_mir;
-use util::liveness;
+use util::liveness::{self, LivenessMode};
 use rustc_const_math::ConstInt;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -348,7 +348,10 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ignored.visit_mir(mir);
 
     let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
-    let liveness = liveness::liveness_of_locals(mir);
+    let liveness = liveness::liveness_of_locals(mir, LivenessMode {
+        include_regular_use: true,
+        include_drops: true,
+    });
     liveness::dump_mir(tcx, "generator_liveness", source, mir, &liveness);
 
     let mut storage_liveness_map = HashMap::new();
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 9d32861aeda..f2453d39461 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -720,6 +720,12 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
                 }
             }
             TerminatorKind::Unreachable => { }
+            TerminatorKind::FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
+                *real_target = self.update_target(*real_target);
+                for target in imaginary_targets {
+                    *target = self.update_target(*target);
+                }
+            }
         }
     }
 
diff --git a/src/librustc_mir/transform/nll/constraint_generation.rs b/src/librustc_mir/transform/nll/constraint_generation.rs
new file mode 100644
index 00000000000..a2f9bbb174e
--- /dev/null
+++ b/src/librustc_mir/transform/nll/constraint_generation.rs
@@ -0,0 +1,274 @@
+// 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.
+
+use rustc::hir;
+use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
+use rustc::mir::transform::MirSource;
+use rustc::mir::visit::Visitor;
+use rustc::mir::Lvalue::Projection;
+use rustc::mir::{LvalueProjection, ProjectionElem};
+use rustc::infer::InferCtxt;
+use rustc::traits::{self, ObligationCause};
+use rustc::ty::{self, Ty};
+use rustc::ty::fold::TypeFoldable;
+use rustc::util::common::ErrorReported;
+use rustc_data_structures::fx::FxHashSet;
+use syntax::codemap::DUMMY_SP;
+
+use super::subtype;
+use super::LivenessResults;
+use super::ToRegionIndex;
+use super::region_infer::RegionInferenceContext;
+
+pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    regioncx: &mut RegionInferenceContext<'tcx>,
+    mir: &Mir<'tcx>,
+    mir_source: MirSource,
+    liveness: &LivenessResults,
+) {
+    ConstraintGeneration {
+        infcx,
+        regioncx,
+        mir,
+        liveness,
+        mir_source,
+    }.add_constraints();
+}
+
+struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+    regioncx: &'cx mut RegionInferenceContext<'tcx>,
+    mir: &'cx Mir<'tcx>,
+    liveness: &'cx LivenessResults,
+    mir_source: MirSource,
+}
+
+impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
+    fn add_constraints(&mut self) {
+        self.add_liveness_constraints();
+        self.add_borrow_constraints();
+    }
+
+    /// Liveness constraints:
+    ///
+    /// > If a variable V is live at point P, then all regions R in the type of V
+    /// > must include the point P.
+    fn add_liveness_constraints(&mut self) {
+        debug!("add_liveness_constraints()");
+        for bb in self.mir.basic_blocks().indices() {
+            debug!("add_liveness_constraints: bb={:?}", bb);
+
+            self.liveness
+                .regular
+                .simulate_block(self.mir, bb, |location, live_locals| {
+                    for live_local in live_locals.iter() {
+                        let live_local_ty = self.mir.local_decls[live_local].ty;
+                        self.add_regular_live_constraint(live_local_ty, location);
+                    }
+                });
+
+            self.liveness
+                .drop
+                .simulate_block(self.mir, bb, |location, live_locals| {
+                    for live_local in live_locals.iter() {
+                        let live_local_ty = self.mir.local_decls[live_local].ty;
+                        self.add_drop_live_constraint(live_local_ty, location);
+                    }
+                });
+        }
+    }
+
+    /// Some variable with type `live_ty` is "regular live" at
+    /// `location` -- i.e., it may be used later. This means that all
+    /// regions appearing in the type `live_ty` must be live at
+    /// `location`.
+    fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "add_regular_live_constraint(live_ty={:?}, location={:?})",
+            live_ty,
+            location
+        );
+
+        self.infcx
+            .tcx
+            .for_each_free_region(&live_ty, |live_region| {
+                let vid = live_region.to_region_index();
+                self.regioncx.add_live_point(vid, location);
+            });
+    }
+
+    /// Some variable with type `live_ty` is "drop live" at `location`
+    /// -- i.e., it may be dropped later. This means that *some* of
+    /// the regions in its type must be live at `location`. The
+    /// precise set will depend on the dropck constraints, and in
+    /// particular this takes `#[may_dangle]` into account.
+    fn add_drop_live_constraint(&mut self, dropped_ty: Ty<'tcx>, location: Location) {
+        debug!(
+            "add_drop_live_constraint(dropped_ty={:?}, location={:?})",
+            dropped_ty,
+            location
+        );
+
+        let tcx = self.infcx.tcx;
+        let mut types = vec![(dropped_ty, 0)];
+        let mut known = FxHashSet();
+        while let Some((ty, depth)) = types.pop() {
+            let span = DUMMY_SP; // FIXME
+            let result = match tcx.dtorck_constraint_for_ty(span, dropped_ty, depth, ty) {
+                Ok(result) => result,
+                Err(ErrorReported) => {
+                    continue;
+                }
+            };
+
+            let ty::DtorckConstraint {
+                outlives,
+                dtorck_types,
+            } = result;
+
+            // All things in the `outlives` array may be touched by
+            // the destructor and must be live at this point.
+            for outlive in outlives {
+                if let Some(ty) = outlive.as_type() {
+                    self.add_regular_live_constraint(ty, location);
+                } else if let Some(r) = outlive.as_region() {
+                    self.add_regular_live_constraint(r, location);
+                } else {
+                    bug!()
+                }
+            }
+
+            // However, there may also be some types that
+            // `dtorck_constraint_for_ty` could not resolve (e.g.,
+            // associated types and parameters). We need to normalize
+            // associated types here and possibly recursively process.
+            let def_id = tcx.hir.local_def_id(self.mir_source.item_id());
+            let param_env = self.infcx.tcx.param_env(def_id);
+            for ty in dtorck_types {
+                // FIXME -- I think that this may disregard some region obligations
+                // or something. Do we care? -nmatsakis
+                let cause = ObligationCause::dummy();
+                match traits::fully_normalize(self.infcx, cause, param_env, &ty) {
+                    Ok(ty) => match ty.sty {
+                        ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
+                            self.add_regular_live_constraint(ty, location);
+                        }
+
+                        _ => if known.insert(ty) {
+                            types.push((ty, depth + 1));
+                        },
+                    },
+
+                    Err(errors) => {
+                        self.infcx.report_fulfillment_errors(&errors, None);
+                    }
+                }
+            }
+        }
+    }
+
+    fn add_borrow_constraints(&mut self) {
+        self.visit_mir(self.mir);
+    }
+
+    fn add_borrow_constraint(
+        &mut self,
+        location: Location,
+        destination_lv: &Lvalue<'tcx>,
+        borrow_region: ty::Region<'tcx>,
+        _borrow_kind: BorrowKind,
+        _borrowed_lv: &Lvalue<'tcx>,
+    ) {
+        let tcx = self.infcx.tcx;
+        let span = self.mir.source_info(location).span;
+        let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
+
+        let destination_region = match destination_ty.sty {
+            ty::TyRef(r, _) => r,
+            _ => bug!()
+        };
+
+        self.regioncx.add_outlives(span,
+                                   borrow_region.to_region_index(),
+                                   destination_region.to_region_index(),
+                                   location.successor_within_block());
+    }
+
+    fn add_reborrow_constraint(
+        &mut self,
+        location: Location,
+        borrow_region: ty::Region<'tcx>,
+        borrowed_lv: &Lvalue<'tcx>,
+    ) {
+        if let Projection(ref proj) = *borrowed_lv {
+            let LvalueProjection { ref base, ref elem } = **proj;
+
+            if let ProjectionElem::Deref = *elem {
+                let tcx = self.infcx.tcx;
+                let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+                let base_sty = &base_ty.sty;
+
+                if let ty::TyRef(base_region, ty::TypeAndMut{ ty: _, mutbl }) = *base_sty {
+                    match mutbl {
+                        hir::Mutability::MutImmutable => { },
+
+                        hir::Mutability::MutMutable => {
+                            self.add_reborrow_constraint(location, borrow_region, base);
+                        },
+                    }
+
+                    let span = self.mir.source_info(location).span;
+                    self.regioncx.add_outlives(span,
+                                               base_region.to_region_index(),
+                                               borrow_region.to_region_index(),
+                                               location.successor_within_block());
+                }
+            }
+        }
+    }
+}
+
+impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cx, 'gcx, 'tcx> {
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &Statement<'tcx>,
+                       location: Location) {
+
+        debug!("visit_statement(statement={:?}, location={:?})", statement, location);
+
+        // Look for a statement like:
+        //
+        //     D = & L
+        //
+        // where D is the path to which we are assigning, and
+        // L is the path that is borrowed.
+        if let StatementKind::Assign(ref destination_lv, ref rv) = statement.kind {
+            if let Rvalue::Ref(region, bk, ref borrowed_lv) = *rv {
+                self.add_borrow_constraint(location, destination_lv, region, bk, borrowed_lv);
+                self.add_reborrow_constraint(location, region, borrowed_lv);
+            }
+
+            let tcx = self.infcx.tcx;
+            let destination_ty = destination_lv.ty(self.mir, tcx).to_ty(tcx);
+            let rv_ty = rv.ty(self.mir, tcx);
+
+            let span = self.mir.source_info(location).span;
+            for (a, b) in subtype::outlives_pairs(tcx, rv_ty, destination_ty) {
+                self.regioncx.add_outlives(span, a, b, location.successor_within_block());
+            }
+        }
+
+        self.super_statement(block, statement, location);
+    }
+}
diff --git a/src/librustc_mir/transform/nll/free_regions.rs b/src/librustc_mir/transform/nll/free_regions.rs
new file mode 100644
index 00000000000..006a2f9047a
--- /dev/null
+++ b/src/librustc_mir/transform/nll/free_regions.rs
@@ -0,0 +1,88 @@
+// 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.
+
+//! Code to extract the free regions declared on a function and the
+//! relationships between them. For example:
+//!
+//! ```
+//! fn foo<'a, 'b, 'c: 'b>() { }
+//! ```
+//!
+//! here we would be returning a map assigning each of `{'a, 'b, 'c}`
+//! to an index, as well as the `FreeRegionMap` which can compute
+//! relationships between them.
+//!
+//! The code in this file doesn't *do anything* with those results; it
+//! just returns them for other code to use.
+
+use rustc::infer::InferCtxt;
+use rustc::middle::free_region::FreeRegionMap;
+use rustc::mir::transform::MirSource;
+use rustc::ty;
+use rustc::ty::subst::Substs;
+use rustc::util::nodemap::FxHashMap;
+
+#[derive(Debug)]
+pub struct FreeRegions<'tcx> {
+    /// Given a free region defined on this function (either early- or
+    /// late-bound), this maps it to its internal region index. The
+    /// corresponding variable will be "capped" so that it cannot
+    /// grow.
+    pub indices: FxHashMap<ty::Region<'tcx>, usize>,
+
+    /// The map from the typeck tables telling us how to relate free regions.
+    pub free_region_map: &'tcx FreeRegionMap<'tcx>,
+}
+
+pub fn free_regions<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    source: MirSource,
+) -> FreeRegions<'tcx> {
+    debug!("free_regions(source={:?})", source);
+
+    let item_id = source.item_id();
+    let item_def_id = infcx.tcx.hir.local_def_id(item_id);
+
+    let mut indices = FxHashMap();
+
+    // 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);
+        }
+    }
+
+    // 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 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);
+            }
+        });
+
+    debug!("free_regions: indices={:#?}", indices);
+
+    FreeRegions { indices, free_region_map: &tables.free_region_map }
+}
+
+fn insert_free_region<'tcx>(
+    free_regions: &mut FxHashMap<ty::Region<'tcx>, usize>,
+    region: ty::Region<'tcx>,
+) {
+    let len = free_regions.len();
+    free_regions.entry(region).or_insert(len);
+}
diff --git a/src/librustc_mir/transform/nll/infer.rs b/src/librustc_mir/transform/nll/infer.rs
deleted file mode 100644
index e6e00f295ca..00000000000
--- a/src/librustc_mir/transform/nll/infer.rs
+++ /dev/null
@@ -1,222 +0,0 @@
-// 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.
-
-use super::{Region, RegionIndex};
-use std::mem;
-use rustc::infer::InferCtxt;
-use rustc::mir::{Location, Mir};
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::fx::FxHashSet;
-
-pub struct InferenceContext {
-    definitions: IndexVec<RegionIndex, VarDefinition>,
-    constraints: IndexVec<ConstraintIndex, Constraint>,
-    errors: IndexVec<InferenceErrorIndex, InferenceError>,
-}
-
-pub struct InferenceError {
-    pub constraint_point: Location,
-    pub name: (), // FIXME(nashenas88) RegionName
-}
-
-newtype_index!(InferenceErrorIndex);
-
-struct VarDefinition {
-    name: (), // FIXME(nashenas88) RegionName
-    value: Region,
-    capped: bool,
-}
-
-impl VarDefinition {
-    pub fn new(value: Region) -> Self {
-        Self {
-            name: (),
-            value,
-            capped: false,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct Constraint {
-    sub: RegionIndex,
-    sup: RegionIndex,
-    point: Location,
-}
-
-newtype_index!(ConstraintIndex);
-
-impl InferenceContext {
-    pub fn new(values: IndexVec<RegionIndex, Region>) -> Self {
-        Self {
-            definitions: values.into_iter().map(VarDefinition::new).collect(),
-            constraints: IndexVec::new(),
-            errors: IndexVec::new(),
-        }
-    }
-
-    #[allow(dead_code)]
-    pub fn cap_var(&mut self, v: RegionIndex) {
-        self.definitions[v].capped = true;
-    }
-
-    #[allow(dead_code)]
-    pub fn add_live_point(&mut self, v: RegionIndex, point: Location) {
-        debug!("add_live_point({:?}, {:?})", v, point);
-        let definition = &mut self.definitions[v];
-        if definition.value.add_point(point) {
-            if definition.capped {
-                self.errors.push(InferenceError {
-                    constraint_point: point,
-                    name: definition.name,
-                });
-            }
-        }
-    }
-
-    #[allow(dead_code)]
-    pub fn add_outlives(&mut self, sup: RegionIndex, sub: RegionIndex, point: Location) {
-        debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
-        self.constraints.push(Constraint { sup, sub, point });
-    }
-
-    #[allow(dead_code)]
-    pub fn region(&self, v: RegionIndex) -> &Region {
-        &self.definitions[v].value
-    }
-
-    pub fn solve<'a, 'gcx, 'tcx>(
-        &mut self,
-        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-        mir: &'a Mir<'tcx>,
-    ) -> IndexVec<InferenceErrorIndex, InferenceError>
-    where
-        'gcx: 'tcx + 'a,
-        'tcx: 'a,
-    {
-        let mut changed = true;
-        let mut dfs = Dfs::new(infcx, mir);
-        while changed {
-            changed = false;
-            for constraint in &self.constraints {
-                let sub = &self.definitions[constraint.sub].value.clone();
-                let sup_def = &mut self.definitions[constraint.sup];
-                debug!("constraint: {:?}", constraint);
-                debug!("    sub (before): {:?}", sub);
-                debug!("    sup (before): {:?}", sup_def.value);
-
-                if dfs.copy(sub, &mut sup_def.value, constraint.point) {
-                    changed = true;
-                    if sup_def.capped {
-                        // This is kind of a hack, but when we add a
-                        // constraint, the "point" is always the point
-                        // AFTER the action that induced the
-                        // constraint. So report the error on the
-                        // action BEFORE that.
-                        assert!(constraint.point.statement_index > 0);
-                        let p = Location {
-                            block: constraint.point.block,
-                            statement_index: constraint.point.statement_index - 1,
-                        };
-
-                        self.errors.push(InferenceError {
-                            constraint_point: p,
-                            name: sup_def.name,
-                        });
-                    }
-                }
-
-                debug!("    sup (after) : {:?}", sup_def.value);
-                debug!("    changed     : {:?}", changed);
-            }
-            debug!("\n");
-        }
-
-        mem::replace(&mut self.errors, IndexVec::new())
-    }
-}
-
-struct Dfs<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
-    #[allow(dead_code)]
-    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
-}
-
-impl<'a, 'gcx: 'tcx, 'tcx: 'a> Dfs<'a, 'gcx, 'tcx> {
-    fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
-        Self { infcx, mir }
-    }
-
-    fn copy(
-        &mut self,
-        from_region: &Region,
-        to_region: &mut Region,
-        start_point: Location,
-    ) -> bool {
-        let mut changed = false;
-
-        let mut stack = vec![];
-        let mut visited = FxHashSet();
-
-        stack.push(start_point);
-        while let Some(p) = stack.pop() {
-            debug!("        dfs: p={:?}", p);
-
-            if !from_region.may_contain(p) {
-                debug!("            not in from-region");
-                continue;
-            }
-
-            if !visited.insert(p) {
-                debug!("            already visited");
-                continue;
-            }
-
-            changed |= to_region.add_point(p);
-
-            let block_data = &self.mir[p.block];
-            let successor_points = if p.statement_index < block_data.statements.len() {
-                vec![Location {
-                    statement_index: p.statement_index + 1,
-                    ..p
-                }]
-            } else {
-                block_data.terminator()
-                    .successors()
-                    .iter()
-                    .map(|&basic_block| Location {
-                        statement_index: 0,
-                        block: basic_block,
-                    })
-                    .collect::<Vec<_>>()
-            };
-
-            if successor_points.is_empty() {
-                // FIXME handle free regions
-                // If we reach the END point in the graph, then copy
-                // over any skolemized end points in the `from_region`
-                // and make sure they are included in the `to_region`.
-                // for region_decl in self.infcx.tcx.tables.borrow().free_region_map() {
-                //     // FIXME(nashenas88) figure out skolemized_end points
-                //     let block = self.env.graph.skolemized_end(region_decl.name);
-                //     let skolemized_end_point = Location {
-                //         block,
-                //         statement_index: 0,
-                //     };
-                //     changed |= to_region.add_point(skolemized_end_point);
-                // }
-            } else {
-                stack.extend(successor_points);
-            }
-        }
-
-        changed
-    }
-}
diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs
index 805e9c976e4..e24def2292e 100644
--- a/src/librustc_mir/transform/nll/mod.rs
+++ b/src/librustc_mir/transform/nll/mod.rs
@@ -8,185 +8,194 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use self::infer::InferenceContext;
-use rustc::ty::TypeFoldable;
-use rustc::ty::subst::{Kind, Substs};
-use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
-use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
-use rustc::mir::visit::{MutVisitor, Lookup};
-use rustc::mir::transform::{MirPass, MirSource};
-use rustc::infer::{self as rustc_infer, InferCtxt};
-use rustc::util::nodemap::FxHashSet;
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
-use syntax_pos::DUMMY_SP;
-use std::collections::HashMap;
-use std::fmt;
+use rustc::ty::{self, RegionKind};
+use rustc::mir::Mir;
+use rustc::mir::transform::MirSource;
+use rustc::infer::InferCtxt;
+use rustc::util::nodemap::FxHashMap;
+use rustc_data_structures::indexed_vec::Idx;
+use std::collections::BTreeSet;
+use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
 
 use util as mir_util;
 use self::mir_util::PassWhere;
 
-mod infer;
-
-#[allow(dead_code)]
-struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
-    lookup_map: HashMap<RegionVid, Lookup>,
-    regions: IndexVec<RegionIndex, Region>,
-    #[allow(dead_code)]
-    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+mod constraint_generation;
+mod free_regions;
+mod subtype;
+
+pub(crate) mod region_infer;
+use self::region_infer::RegionInferenceContext;
+
+mod renumber;
+
+/// Computes the (non-lexical) regions from the input MIR.
+///
+/// This may result in errors being reported.
+pub fn compute_regions<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    source: MirSource,
+    mir: &mut Mir<'tcx>,
+) -> RegionInferenceContext<'tcx> {
+    // Compute named region information.
+    let free_regions = &free_regions::free_regions(infcx, source);
+
+    // Replace all regions with fresh inference variables.
+    let num_region_variables = renumber::renumber_mir(infcx, free_regions, mir);
+
+    // Compute what is live where.
+    let liveness = &LivenessResults {
+        regular: liveness::liveness_of_locals(
+            &mir,
+            LivenessMode {
+                include_regular_use: true,
+                include_drops: false,
+            },
+        ),
+
+        drop: liveness::liveness_of_locals(
+            &mir,
+            LivenessMode {
+                include_regular_use: false,
+                include_drops: true,
+            },
+        ),
+    };
+
+    // Create the region inference context, generate the constraints,
+    // and then solve them.
+    let mut regioncx = RegionInferenceContext::new(free_regions, num_region_variables, mir);
+    constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness);
+    regioncx.solve(infcx, &mir);
+
+    // Dump MIR results into a file, if that is enabled. This let us
+    // write unit-tests.
+    dump_mir_results(infcx, liveness, source, &mir, &regioncx);
+
+    regioncx
 }
 
-impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self {
-        NLLVisitor {
-            infcx,
-            lookup_map: HashMap::new(),
-            regions: IndexVec::new(),
-        }
-    }
+struct LivenessResults {
+    regular: LivenessResult,
+    drop: LivenessResult,
+}
 
-    pub fn into_results(self) -> (HashMap<RegionVid, Lookup>, IndexVec<RegionIndex, Region>) {
-        (self.lookup_map, self.regions)
+fn dump_mir_results<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    liveness: &LivenessResults,
+    source: MirSource,
+    mir: &Mir<'tcx>,
+    regioncx: &RegionInferenceContext,
+) {
+    if !mir_util::dump_enabled(infcx.tcx, "nll", source) {
+        return;
     }
 
-    fn renumber_regions<T>(&mut self, value: &T) -> T where T: TypeFoldable<'tcx> {
-        self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
-            self.regions.push(Region::default());
-            self.infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
+    let regular_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
+        .indices()
+        .flat_map(|bb| {
+            let mut results = vec![];
+            liveness
+                .regular
+                .simulate_block(&mir, bb, |location, local_set| {
+                    results.push((location, local_set.clone()));
+                });
+            results
         })
-    }
-
-    fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
-        if let RegionKind::ReVar(rid) = *region {
-            self.lookup_map.entry(rid).or_insert(lookup);
-        }
-    }
+        .collect();
+
+    let drop_liveness_per_location: FxHashMap<_, _> = mir.basic_blocks()
+        .indices()
+        .flat_map(|bb| {
+            let mut results = vec![];
+            liveness
+                .drop
+                .simulate_block(&mir, bb, |location, local_set| {
+                    results.push((location, local_set.clone()));
+                });
+            results
+        })
+        .collect();
+
+    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(region)
+                )?;
+            },
+
+            // Before each basic block, dump out the values
+            // that are live on entry to the basic block.
+            PassWhere::BeforeBlock(bb) => {
+                let s = live_variable_set(&liveness.regular.ins[bb], &liveness.drop.ins[bb]);
+                writeln!(out, "    | Live variables on entry to {:?}: {}", bb, s)?;
+            }
 
-    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
-        for region in ty.regions() {
-            self.store_region(region, lookup);
-        }
-    }
+            PassWhere::InCFG(location) => {
+                let s = live_variable_set(
+                    &regular_liveness_per_location[&location],
+                    &drop_liveness_per_location[&location],
+                );
+                writeln!(out, "            | Live variables at {:?}: {}", location, s)?;
+            }
 
-    fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
-        if let Some(ty) = kind.as_type() {
-            self.store_ty_regions(&ty, lookup);
-        } else if let Some(region) = kind.as_region() {
-            self.store_region(region, lookup);
+            PassWhere::AfterCFG => {}
         }
-    }
+        Ok(())
+    });
 }
 
-impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
-    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
-        let old_ty = *ty;
-        *ty = self.renumber_regions(&old_ty);
-        self.store_ty_regions(ty, lookup);
-    }
-
-    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
-        *substs = self.renumber_regions(&{*substs});
-        let lookup = Lookup::Loc(location);
-        for kind in *substs {
-            self.store_kind_regions(kind, lookup);
-        }
-    }
-
-    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
-        match *rvalue {
-            Rvalue::Ref(ref mut r, _, _) => {
-                let old_r = *r;
-                *r = self.renumber_regions(&old_r);
-                let lookup = Lookup::Loc(location);
-                self.store_region(r, lookup);
-            }
-            Rvalue::Use(..) |
-            Rvalue::Repeat(..) |
-            Rvalue::Len(..) |
-            Rvalue::Cast(..) |
-            Rvalue::BinaryOp(..) |
-            Rvalue::CheckedBinaryOp(..) |
-            Rvalue::UnaryOp(..) |
-            Rvalue::Discriminant(..) |
-            Rvalue::NullaryOp(..) |
-            Rvalue::Aggregate(..) => {
-                // These variants don't contain regions.
-            }
-        }
-        self.super_rvalue(rvalue, location);
-    }
-
-    fn visit_closure_substs(&mut self,
-                            substs: &mut ClosureSubsts<'tcx>,
-                            location: Location) {
-        *substs = self.renumber_regions(substs);
-        let lookup = Lookup::Loc(location);
-        for kind in substs.substs {
-            self.store_kind_regions(kind, lookup);
-        }
-    }
+newtype_index!(RegionIndex {
+    DEBUG_FORMAT = "'_#{}r",
+});
+
+/// Right now, we piggy back on the `ReVar` to store our NLL inference
+/// regions. These are indexed with `RegionIndex`. This method will
+/// assert that the region is a `ReVar` and convert the internal index
+/// into a `RegionIndex`. This is reasonable because in our MIR we
+/// replace all free regions with inference variables.
+pub trait ToRegionIndex {
+    fn to_region_index(&self) -> RegionIndex;
+}
 
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &mut Statement<'tcx>,
-                       location: Location) {
-        if let StatementKind::EndRegion(_) = statement.kind {
-            statement.kind = StatementKind::Nop;
+impl ToRegionIndex for RegionKind {
+    fn to_region_index(&self) -> RegionIndex {
+        if let &ty::ReVar(vid) = self {
+            RegionIndex::new(vid.index as usize)
+        } else {
+            bug!("region is not an ReVar: {:?}", self)
         }
-        self.super_statement(block, statement, location);
     }
 }
 
-// MIR Pass for non-lexical lifetimes
-pub struct NLL;
+fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String {
+    // sort and deduplicate:
+    let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect();
 
-impl MirPass for NLL {
-    fn run_pass<'a, 'tcx>(&self,
-                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          source: MirSource,
-                          mir: &mut Mir<'tcx>) {
-        if !tcx.sess.opts.debugging_opts.nll {
-            return;
-        }
+    // construct a string with each local, including `(drop)` if it is
+    // only dropped, versus a regular use.
+    let mut string = String::new();
+    for local in all_locals {
+        string.push_str(&format!("{:?}", local));
 
-        tcx.infer_ctxt().enter(|infcx| {
-            // Clone mir so we can mutate it without disturbing the rest of the compiler
-            let mut renumbered_mir = mir.clone();
-            let mut visitor = NLLVisitor::new(&infcx);
-            visitor.visit_mir(&mut renumbered_mir);
-            mir_util::dump_mir(tcx, None, "nll", &0, source, mir, |pass_where, out| {
-                if let PassWhere::BeforeCFG = pass_where {
-                    for (index, value) in visitor.regions.iter_enumerated() {
-                        writeln!(out, "// R{:03}: {:?}", index.0, value)?;
-                    }
-                }
-                Ok(())
-            });
-            let (_lookup_map, regions) = visitor.into_results();
-            let mut inference_context = InferenceContext::new(regions);
-            inference_context.solve(&infcx, &renumbered_mir);
-        })
-    }
-}
-
-#[derive(Clone, Default, PartialEq, Eq)]
-pub struct Region {
-    points: FxHashSet<Location>,
-}
+        if !regular.contains(&local) {
+            assert!(drops.contains(&local));
+            string.push_str(" (drop)");
+        }
 
-impl fmt::Debug for Region {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        write!(formatter, "{:?}", self.points)
+        string.push_str(", ");
     }
-}
 
-impl Region {
-    pub fn add_point(&mut self, point: Location) -> bool {
-        self.points.insert(point)
-    }
+    let len = if string.is_empty() {
+        0
+    } else {
+        string.len() - 2
+    };
 
-    pub fn may_contain(&self, point: Location) -> bool {
-        self.points.contains(&point)
-    }
+    format!("[{}]", &string[..len])
 }
-
-newtype_index!(RegionIndex);
diff --git a/src/librustc_mir/transform/nll/region_infer.rs b/src/librustc_mir/transform/nll/region_infer.rs
new file mode 100644
index 00000000000..553d5ad4a32
--- /dev/null
+++ b/src/librustc_mir/transform/nll/region_infer.rs
@@ -0,0 +1,400 @@
+// 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.
+
+use super::RegionIndex;
+use super::free_regions::FreeRegions;
+use rustc::infer::InferCtxt;
+use rustc::mir::{Location, Mir};
+use rustc::ty;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::fx::FxHashSet;
+use std::collections::BTreeSet;
+use std::fmt;
+use syntax_pos::Span;
+
+pub struct RegionInferenceContext<'tcx> {
+    /// Contains the definition for every region variable.  Region
+    /// variables are identified by their index (`RegionIndex`). The
+    /// definition contains information about where the region came
+    /// from as well as its final inferred value.
+    definitions: IndexVec<RegionIndex, RegionDefinition<'tcx>>,
+
+    /// The indices of all "free regions" in scope. These are the
+    /// lifetime parameters (anonymous and named) declared in the
+    /// function signature:
+    ///
+    ///     fn foo<'a, 'b>(x: &Foo<'a, 'b>)
+    ///            ^^  ^^     ^
+    ///
+    /// These indices will be from 0..N, as it happens, but we collect
+    /// them into a vector for convenience.
+    free_regions: Vec<RegionIndex>,
+
+    /// The constraints we have accumulated and used during solving.
+    constraints: Vec<Constraint>,
+}
+
+#[derive(Default)]
+struct RegionDefinition<'tcx> {
+    /// If this is a free-region, then this is `Some(X)` where `X` is
+    /// the name of the region.
+    name: Option<ty::Region<'tcx>>,
+
+    /// If true, this is a constant region which cannot grow larger.
+    /// This is used for named regions as well as `'static`.
+    constant: bool,
+
+    /// The current value of this inference variable. This starts out
+    /// empty, but grows as we add constraints. The final value is
+    /// determined when `solve()` is executed.
+    value: Region,
+}
+
+/// The value of an individual region variable. Region variables
+/// consist of a set of points in the CFG as well as a set of "free
+/// regions", which are sometimes written as `end(R)`. These
+/// correspond to the named lifetimes and refer to portions of the
+/// caller's control-flow graph -- specifically some portion that can
+/// be reached after we return.
+#[derive(Clone, Default, PartialEq, Eq)]
+struct Region {
+    points: BTreeSet<Location>,
+    free_regions: BTreeSet<RegionIndex>,
+}
+
+impl fmt::Debug for Region {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        formatter
+            .debug_set()
+            .entries(&self.points)
+            .entries(&self.free_regions)
+            .finish()
+    }
+}
+
+impl Region {
+    fn add_point(&mut self, point: Location) -> bool {
+        self.points.insert(point)
+    }
+
+    fn add_free_region(&mut self, region: RegionIndex) -> bool {
+        self.free_regions.insert(region)
+    }
+
+    fn contains_point(&self, point: Location) -> bool {
+        self.points.contains(&point)
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct Constraint {
+    /// Where did this constraint arise?
+    span: Span,
+
+    /// The region SUP must outlive SUB...
+    sup: RegionIndex,
+
+    /// Region that must be outlived.
+    sub: RegionIndex,
+
+    /// At this location.
+    point: Location,
+}
+
+impl<'a, 'gcx, 'tcx> RegionInferenceContext<'tcx> {
+    /// Creates a new region inference context with a total of
+    /// `num_region_variables` valid inference variables; the first N
+    /// of those will be constant regions representing the free
+    /// regions defined in `free_regions`.
+    pub fn new(
+        free_regions: &FreeRegions<'tcx>,
+        num_region_variables: usize,
+        mir: &Mir<'tcx>,
+    ) -> Self {
+        let mut result = Self {
+            definitions: (0..num_region_variables)
+                .map(|_| RegionDefinition::default())
+                .collect(),
+            constraints: Vec::new(),
+            free_regions: Vec::new(),
+        };
+
+        result.init_free_regions(free_regions, mir);
+
+        result
+    }
+
+    /// Initializes the region variables for each free region
+    /// (lifetime parameter). The first N variables always correspond
+    /// to the free regions appearing in the function signature (both
+    /// named and anonymous) and where clauses. This function iterates
+    /// over those regions and initializes them with minimum values.
+    ///
+    /// For example:
+    ///
+    ///     fn foo<'a, 'b>(..) where 'a: 'b
+    ///
+    /// would initialize two variables like so:
+    ///
+    ///     R0 = { CFG, R0 } // 'a
+    ///     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_free_regions(&mut self, free_regions: &FreeRegions<'tcx>, mir: &Mir<'tcx>) {
+        let &FreeRegions {
+            ref indices,
+            ref free_region_map,
+        } = free_regions;
+
+        // For each free region X:
+        for (free_region, index) in indices {
+            let variable = RegionIndex::new(*index);
+
+            self.free_regions.push(variable);
+
+            // Initialize the name and a few other details.
+            self.definitions[variable].name = Some(free_region);
+            self.definitions[variable].constant = true;
+
+            // Add all nodes in the CFG to `definition.value`.
+            for (block, block_data) in mir.basic_blocks().iter_enumerated() {
+                let definition = &mut self.definitions[variable];
+                for statement_index in 0..block_data.statements.len() + 1 {
+                    let location = Location {
+                        block,
+                        statement_index,
+                    };
+                    definition.value.add_point(location);
+                }
+            }
+
+            // Add `end(X)` into the set for X.
+            self.definitions[variable].value.add_free_region(variable);
+
+            // Go through each region Y that outlives X (i.e., where
+            // Y: X is true). Add `end(X)` into the set for `Y`.
+            for superregion in free_region_map.regions_that_outlive(&free_region) {
+                let superregion_index = RegionIndex::new(indices[superregion]);
+                self.definitions[superregion_index]
+                    .value
+                    .add_free_region(variable);
+            }
+
+            debug!(
+                "init_free_regions: region variable for `{:?}` is `{:?}` with value `{:?}`",
+                free_region,
+                variable,
+                self.definitions[variable].value
+            );
+        }
+    }
+
+    /// Returns an iterator over all the region indices.
+    pub fn regions(&self) -> impl Iterator<Item = RegionIndex> {
+        self.definitions.indices()
+    }
+
+    /// Returns true if the region `r` contains the point `p`.
+    ///
+    /// Until `solve()` executes, this value is not particularly meaningful.
+    pub fn region_contains_point(&self, r: RegionIndex, p: Location) -> bool {
+        self.definitions[r].value.contains_point(p)
+    }
+
+    /// Returns access to the value of `r` for debugging purposes.
+    pub(super) fn region_value(&self, r: RegionIndex) -> &fmt::Debug {
+        &self.definitions[r].value
+    }
+
+    /// Indicates that the region variable `v` is live at the point `point`.
+    pub(super) fn add_live_point(&mut self, v: RegionIndex, point: Location) {
+        debug!("add_live_point({:?}, {:?})", v, point);
+        let definition = &mut self.definitions[v];
+        if !definition.constant {
+            definition.value.add_point(point);
+        } else {
+            // Constants are used for free regions, which already
+            // contain all the points in the control-flow graph.
+            assert!(definition.value.contains_point(point));
+        }
+    }
+
+    /// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`.
+    pub(super) fn add_outlives(
+        &mut self,
+        span: Span,
+        sup: RegionIndex,
+        sub: RegionIndex,
+        point: Location,
+    ) {
+        debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point);
+        self.constraints.push(Constraint {
+            span,
+            sup,
+            sub,
+            point,
+        });
+    }
+
+    /// Perform region inference.
+    pub(super) fn solve(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, mir: &Mir<'tcx>) {
+        let errors = self.propagate_constraints(mir);
+
+        // worst error msg ever
+        for (fr1, span, fr2) in errors {
+            infcx.tcx.sess.span_err(
+                span,
+                &format!(
+                    "free region `{}` does not outlive `{}`",
+                    self.definitions[fr1].name.unwrap(),
+                    self.definitions[fr2].name.unwrap()
+                ),
+            );
+        }
+    }
+
+    /// 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
+    /// feasible, but we check this later.
+    fn propagate_constraints(
+        &mut self,
+        mir: &Mir<'tcx>,
+    ) -> Vec<(RegionIndex, Span, RegionIndex)> {
+        let mut changed = true;
+        let mut dfs = Dfs::new(mir);
+        let mut error_regions = FxHashSet();
+        let mut errors = vec![];
+        while changed {
+            changed = false;
+            for constraint in &self.constraints {
+                debug!("constraint: {:?}", constraint);
+                let sub = &self.definitions[constraint.sub].value.clone();
+                let sup_def = &mut self.definitions[constraint.sup];
+
+                debug!("    sub (before): {:?}", sub);
+                debug!("    sup (before): {:?}", sup_def.value);
+
+                if !sup_def.constant {
+                    // If this is not a constant, then grow the value as needed to
+                    // accommodate the outlives constraint.
+
+                    if dfs.copy(sub, &mut sup_def.value, constraint.point) {
+                        changed = true;
+                    }
+
+                    debug!("    sup (after) : {:?}", sup_def.value);
+                    debug!("    changed     : {:?}", changed);
+                } else {
+                    // If this is a constant, check whether it *would
+                    // have* to grow in order for the constraint to be
+                    // satisfied. If so, create an error.
+
+                    let mut sup_value = sup_def.value.clone();
+                    if dfs.copy(sub, &mut sup_value, constraint.point) {
+                        // Constant values start out with the entire
+                        // CFG, so it must be some new free region
+                        // that was added. Find one.
+                        let &new_region = sup_value
+                            .free_regions
+                            .difference(&sup_def.value.free_regions)
+                            .next()
+                            .unwrap();
+                        debug!("    new_region : {:?}", new_region);
+                        if error_regions.insert(constraint.sup) {
+                            errors.push((constraint.sup, constraint.span, new_region));
+                        }
+                    }
+                }
+            }
+            debug!("\n");
+        }
+        errors
+    }
+}
+
+struct Dfs<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx> Dfs<'a, 'tcx> {
+    fn new(mir: &'a Mir<'tcx>) -> Self {
+        Self { mir }
+    }
+
+    fn copy(
+        &mut self,
+        from_region: &Region,
+        to_region: &mut Region,
+        start_point: Location,
+    ) -> bool {
+        let mut changed = false;
+
+        let mut stack = vec![];
+        let mut visited = FxHashSet();
+
+        stack.push(start_point);
+        while let Some(p) = stack.pop() {
+            debug!("        dfs: p={:?}", p);
+
+            if !from_region.contains_point(p) {
+                debug!("            not in from-region");
+                continue;
+            }
+
+            if !visited.insert(p) {
+                debug!("            already visited");
+                continue;
+            }
+
+            changed |= to_region.add_point(p);
+
+            let block_data = &self.mir[p.block];
+            let successor_points = if p.statement_index < block_data.statements.len() {
+                vec![
+                    Location {
+                        statement_index: p.statement_index + 1,
+                        ..p
+                    },
+                ]
+            } else {
+                block_data
+                    .terminator()
+                    .successors()
+                    .iter()
+                    .map(|&basic_block| {
+                        Location {
+                            statement_index: 0,
+                            block: basic_block,
+                        }
+                    })
+                    .collect::<Vec<_>>()
+            };
+
+            if successor_points.is_empty() {
+                // If we reach the END point in the graph, then copy
+                // over any skolemized end points in the `from_region`
+                // and make sure they are included in the `to_region`.
+
+                debug!("        dfs: free_regions={:?}", from_region.free_regions);
+                for &fr in &from_region.free_regions {
+                    changed |= to_region.free_regions.insert(fr);
+                }
+            } else {
+                stack.extend(successor_points);
+            }
+        }
+
+        changed
+    }
+}
diff --git a/src/librustc_mir/transform/nll/renumber.rs b/src/librustc_mir/transform/nll/renumber.rs
new file mode 100644
index 00000000000..a3ff7a041ca
--- /dev/null
+++ b/src/librustc_mir/transform/nll/renumber.rs
@@ -0,0 +1,182 @@
+// 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.
+
+use rustc_data_structures::indexed_vec::Idx;
+use rustc::ty::subst::{Kind, Substs};
+use rustc::ty::{self, ClosureSubsts, RegionKind, RegionVid, Ty, TypeFoldable};
+use rustc::mir::{BasicBlock, Local, Location, Mir, Rvalue, Statement, StatementKind};
+use rustc::mir::visit::{MutVisitor, TyContext};
+use rustc::infer::{self as rustc_infer, InferCtxt};
+use syntax_pos::DUMMY_SP;
+use std::collections::HashMap;
+
+use super::free_regions::FreeRegions;
+
+/// Replaces all free regions appearing in the MIR with fresh
+/// inference variables, returning the number of variables created.
+pub fn renumber_mir<'a, 'gcx, 'tcx>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    free_regions: &FreeRegions<'tcx>,
+    mir: &mut Mir<'tcx>,
+) -> usize {
+    // Create inference variables for each of the free regions
+    // declared on the function signature.
+    let free_region_inference_vars = (0..free_regions.indices.len())
+        .map(|_| {
+            infcx.next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
+        })
+        .collect();
+
+    let mut visitor = NLLVisitor {
+        infcx,
+        lookup_map: HashMap::new(),
+        num_region_variables: free_regions.indices.len(),
+        free_regions,
+        free_region_inference_vars,
+        arg_count: mir.arg_count,
+    };
+    visitor.visit_mir(mir);
+    visitor.num_region_variables
+}
+
+struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    lookup_map: HashMap<RegionVid, TyContext>,
+    num_region_variables: usize,
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    free_regions: &'a FreeRegions<'tcx>,
+    free_region_inference_vars: Vec<ty::Region<'tcx>>,
+    arg_count: usize,
+}
+
+impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
+    /// Replaces all regions appearing in `value` with fresh inference
+    /// variables. This is what we do for almost the entire MIR, with
+    /// the exception of the declared types of our arguments.
+    fn renumber_regions<T>(&mut self, value: &T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.infcx
+            .tcx
+            .fold_regions(value, &mut false, |_region, _depth| {
+                self.num_region_variables += 1;
+                self.infcx
+                    .next_region_var(rustc_infer::MiscVariable(DUMMY_SP))
+            })
+    }
+
+    /// Renumbers the regions appearing in `value`, but those regions
+    /// are expected to be free regions from the function signature.
+    fn renumber_free_regions<T>(&mut self, value: &T) -> T
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        self.infcx
+            .tcx
+            .fold_regions(value, &mut false, |region, _depth| {
+                let index = self.free_regions.indices[&region];
+                self.free_region_inference_vars[index]
+            })
+    }
+
+    fn store_region(&mut self, region: &RegionKind, lookup: TyContext) {
+        if let RegionKind::ReVar(rid) = *region {
+            self.lookup_map.entry(rid).or_insert(lookup);
+        }
+    }
+
+    fn store_ty_regions(&mut self, ty: &Ty<'tcx>, ty_context: TyContext) {
+        for region in ty.regions() {
+            self.store_region(region, ty_context);
+        }
+    }
+
+    fn store_kind_regions(&mut self, kind: &'tcx Kind, ty_context: TyContext) {
+        if let Some(ty) = kind.as_type() {
+            self.store_ty_regions(&ty, ty_context);
+        } else if let Some(region) = kind.as_region() {
+            self.store_region(region, ty_context);
+        }
+    }
+
+    fn is_argument_or_return_slot(&self, local: Local) -> bool {
+        // The first argument is return slot, next N are arguments.
+        local.index() <= self.arg_count
+    }
+}
+
+impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
+    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
+        let is_arg = match ty_context {
+            TyContext::LocalDecl { local, .. } => self.is_argument_or_return_slot(local),
+            _ => false,
+        };
+
+        let old_ty = *ty;
+        *ty = if is_arg {
+            self.renumber_free_regions(&old_ty)
+        } else {
+            self.renumber_regions(&old_ty)
+        };
+        self.store_ty_regions(ty, ty_context);
+    }
+
+    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
+        *substs = self.renumber_regions(&{ *substs });
+        let ty_context = TyContext::Location(location);
+        for kind in *substs {
+            self.store_kind_regions(kind, ty_context);
+        }
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
+        match *rvalue {
+            Rvalue::Ref(ref mut r, _, _) => {
+                let old_r = *r;
+                *r = self.renumber_regions(&old_r);
+                let ty_context = TyContext::Location(location);
+                self.store_region(r, ty_context);
+            }
+            Rvalue::Use(..) |
+            Rvalue::Repeat(..) |
+            Rvalue::Len(..) |
+            Rvalue::Cast(..) |
+            Rvalue::BinaryOp(..) |
+            Rvalue::CheckedBinaryOp(..) |
+            Rvalue::UnaryOp(..) |
+            Rvalue::Discriminant(..) |
+            Rvalue::NullaryOp(..) |
+            Rvalue::Aggregate(..) => {
+                // These variants don't contain regions.
+            }
+        }
+        self.super_rvalue(rvalue, location);
+    }
+
+    fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
+        *substs = self.renumber_regions(substs);
+        let ty_context = TyContext::Location(location);
+        for kind in substs.substs {
+            self.store_kind_regions(kind, ty_context);
+        }
+    }
+
+    fn visit_statement(
+        &mut self,
+        block: BasicBlock,
+        statement: &mut Statement<'tcx>,
+        location: Location,
+    ) {
+        if let StatementKind::EndRegion(_) = statement.kind {
+            statement.kind = StatementKind::Nop;
+        }
+        self.super_statement(block, statement, location);
+    }
+}
diff --git a/src/librustc_mir/transform/nll/subtype.rs b/src/librustc_mir/transform/nll/subtype.rs
new file mode 100644
index 00000000000..953fc0eb733
--- /dev/null
+++ b/src/librustc_mir/transform/nll/subtype.rs
@@ -0,0 +1,99 @@
+// 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.
+
+use super::RegionIndex;
+use transform::nll::ToRegionIndex;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
+
+pub fn outlives_pairs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                      a: Ty<'tcx>,
+                      b: Ty<'tcx>)
+                      -> Vec<(RegionIndex, RegionIndex)>
+{
+    let mut subtype = Subtype::new(tcx);
+    match subtype.relate(&a, &b) {
+        Ok(_) => subtype.outlives_pairs,
+
+        Err(_) => bug!("Fail to relate a = {:?} and b = {:?}", a, b)
+    }
+}
+
+struct Subtype<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    outlives_pairs: Vec<(RegionIndex, RegionIndex)>,
+    ambient_variance: ty::Variance,
+}
+
+impl<'a, 'gcx, 'tcx> Subtype<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Subtype<'a, 'gcx, 'tcx> {
+        Subtype {
+            tcx,
+            outlives_pairs: vec![],
+            ambient_variance: ty::Covariant,
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Subtype<'a, 'gcx, 'tcx> {
+    fn tag(&self) -> &'static str { "Subtype" }
+    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx }
+    fn a_is_expected(&self) -> bool { true } // irrelevant
+
+    fn relate_with_variance<T: Relate<'tcx>>(&mut self,
+                                             variance: ty::Variance,
+                                             a: &T,
+                                             b: &T)
+                                             -> RelateResult<'tcx, T>
+    {
+        let old_ambient_variance = self.ambient_variance;
+        self.ambient_variance = self.ambient_variance.xform(variance);
+
+        let result = self.relate(a, b);
+        self.ambient_variance = old_ambient_variance;
+        result
+    }
+
+    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        relate::super_relate_tys(self, t, t2)
+    }
+
+    fn regions(&mut self, r_a: ty::Region<'tcx>, r_b: ty::Region<'tcx>)
+               -> RelateResult<'tcx, ty::Region<'tcx>> {
+        let a = r_a.to_region_index();
+        let b = r_b.to_region_index();
+
+        match self.ambient_variance {
+            ty::Covariant => {
+                self.outlives_pairs.push((b, a));
+            },
+
+            ty::Invariant => {
+                self.outlives_pairs.push((a, b));
+                self.outlives_pairs.push((b, a));
+            },
+
+            ty::Contravariant => {
+                self.outlives_pairs.push((a, b));
+            },
+
+            ty::Bivariant => {},
+        }
+
+        Ok(r_a)
+    }
+
+    fn binders<T>(&mut self, _a: &ty::Binder<T>, _b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'tcx>
+    {
+        unimplemented!();
+    }
+}
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index fa6bb644871..7de8de3c96b 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -45,7 +45,8 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
             TerminatorKind::Unreachable |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Yield { .. } |
-            TerminatorKind::SwitchInt { .. } => {
+            TerminatorKind::SwitchInt { .. } |
+            TerminatorKind::FalseEdges { .. } => {
                 /* nothing to do */
             },
             TerminatorKind::Call { cleanup: ref mut unwind, .. } |
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 3f3b9d177d7..583dfd9b616 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -317,7 +317,8 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                 TerminatorKind::Resume |
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Yield { .. } |
-                TerminatorKind::Unreachable => None,
+                TerminatorKind::Unreachable |
+                TerminatorKind::FalseEdges { .. } => None,
 
                 TerminatorKind::Return => {
                     // Check for unused values. This usually means
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 0dff145ecbc..edbbe5305e9 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -61,6 +61,9 @@ impl MirPass for SimplifyBranches {
                 }), expected, .. } if cond == expected => {
                     TerminatorKind::Goto { target: target }
                 },
+                TerminatorKind::FalseEdges { real_target, .. } => {
+                    TerminatorKind::Goto { target: real_target }
+                },
                 _ => continue
             };
         }
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index ab5998a3480..b07e818ee87 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -92,8 +92,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         self.sanitize_type(rvalue, rval_ty);
     }
 
-    fn visit_local_decl(&mut self, local_decl: &LocalDecl<'tcx>) {
-        self.super_local_decl(local_decl);
+    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+        self.super_local_decl(local, local_decl);
         self.sanitize_type(local_decl, local_decl.ty);
     }
 
@@ -441,7 +441,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             TerminatorKind::Return |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Unreachable |
-            TerminatorKind::Drop { .. } => {
+            TerminatorKind::Drop { .. } |
+            TerminatorKind::FalseEdges { .. } => {
                 // no checks needed for these
             }
 
@@ -685,6 +686,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     self.assert_iscleanup(mir, block, cleanup, true);
                 }
             }
+            TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+                self.assert_iscleanup(mir, block, real_target, is_cleanup);
+                for target in imaginary_targets {
+                    self.assert_iscleanup(mir, block, *target, is_cleanup);
+                }
+            }
         }
     }
 
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 5451da2148e..2f29b79eeb6 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::{self, TyCtxt};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use syntax_pos::{MultiSpan, Span};
 
 use std::fmt;
@@ -41,7 +41,7 @@ pub trait BorrowckErrors {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>;
 
     fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
@@ -93,7 +93,7 @@ pub trait BorrowckErrors {
                                       opt_via: &str,
                                       old_loan_span: Span,
                                       old_opt_via: &str,
-                                      old_load_end_span:Span,
+                                      old_load_end_span: Option<Span>,
                                       o: Origin)
                                       -> DiagnosticBuilder
     {
@@ -106,13 +106,17 @@ pub trait BorrowckErrors {
             err.span_label(new_loan_span,
                            format!("mutable borrow starts here in previous \
                                     iteration of loop{}", opt_via));
-            err.span_label(old_load_end_span, "mutable borrow ends here");
+            if let Some(old_load_end_span) = old_load_end_span {
+                err.span_label(old_load_end_span, "mutable borrow ends here");
+            }
         } else {
             err.span_label(old_loan_span,
                            format!("first mutable borrow occurs here{}", old_opt_via));
             err.span_label(new_loan_span,
                            format!("second mutable borrow occurs here{}", opt_via));
-            err.span_label(old_load_end_span, "first borrow ends here");
+            if let Some(old_load_end_span) = old_load_end_span {
+                err.span_label(old_load_end_span, "first borrow ends here");
+            }
         }
         err
     }
@@ -121,7 +125,7 @@ pub trait BorrowckErrors {
                                               new_loan_span: Span,
                                               desc: &str,
                                               old_loan_span: Span,
-                                              old_load_end_span: Span,
+                                              old_load_end_span: Option<Span>,
                                               o: Origin)
                                               -> DiagnosticBuilder
     {
@@ -134,9 +138,11 @@ pub trait BorrowckErrors {
         err.span_label(
             new_loan_span,
             "second closure is constructed here");
-        err.span_label(
-            old_load_end_span,
-            "borrow from first closure ends here");
+        if let Some(old_load_end_span) = old_load_end_span {
+            err.span_label(
+                old_load_end_span,
+                "borrow from first closure ends here");
+        }
         err
     }
 
@@ -147,7 +153,7 @@ pub trait BorrowckErrors {
                                              old_loan_span: Span,
                                              noun_old: &str,
                                              old_opt_via: &str,
-                                             previous_end_span: Span,
+                                             previous_end_span: Option<Span>,
                                              o: Origin)
                                              -> DiagnosticBuilder
     {
@@ -158,7 +164,9 @@ pub trait BorrowckErrors {
                        format!("closure construction occurs here{}", opt_via));
         err.span_label(old_loan_span,
                        format!("borrow occurs here{}", old_opt_via));
-        err.span_label(previous_end_span, "borrow ends here");
+        if let Some(previous_end_span) = previous_end_span {
+            err.span_label(previous_end_span, "borrow ends here");
+        }
         err
     }
 
@@ -169,7 +177,7 @@ pub trait BorrowckErrors {
                                                  kind_new: &str,
                                                  old_loan_span: Span,
                                                  old_opt_via: &str,
-                                                 previous_end_span: Span,
+                                                 previous_end_span: Option<Span>,
                                                  o: Origin)
                                                  -> DiagnosticBuilder
     {
@@ -181,7 +189,9 @@ pub trait BorrowckErrors {
                        format!("borrow occurs here{}", opt_via));
         err.span_label(old_loan_span,
                        format!("closure construction occurs here{}", old_opt_via));
-        err.span_label(previous_end_span, "borrow from closure ends here");
+        if let Some(previous_end_span) = previous_end_span {
+            err.span_label(previous_end_span, "borrow from closure ends here");
+        }
         err
     }
 
@@ -194,7 +204,7 @@ pub trait BorrowckErrors {
                                         noun_old: &str,
                                         kind_old: &str,
                                         msg_old: &str,
-                                        old_load_end_span: Span,
+                                        old_load_end_span: Option<Span>,
                                         o: Origin)
                                         -> DiagnosticBuilder
     {
@@ -203,7 +213,9 @@ pub trait BorrowckErrors {
                          desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o);
         err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
         err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, msg_old));
-        err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
+        if let Some(old_load_end_span) = old_load_end_span {
+            err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
+        }
         err
     }
 
@@ -429,11 +441,11 @@ pub trait BorrowckErrors {
     }
 }
 
-impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> {
+impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>
     {
         self.sess.struct_span_err_with_code(sp, msg, code)
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index cec8067530b..a38d317b823 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -21,10 +21,10 @@ use rustc_data_structures::indexed_vec::Idx;
 use super::pretty::dump_mir_def_ids;
 
 /// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'a, 'tcx, W>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                       single: Option<DefId>,
-                                       w: &mut W)
-                                       -> io::Result<()>
+pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
+                                   single: Option<DefId>,
+                                   w: &mut W)
+                                   -> io::Result<()>
     where W: Write
 {
     for def_id in dump_mir_def_ids(tcx, single) {
@@ -36,10 +36,10 @@ pub fn write_mir_graphviz<'a, 'tcx, W>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 /// Write a graphviz DOT graph of the MIR.
-pub fn write_mir_fn_graphviz<'a, 'tcx, W>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        nodeid: NodeId,
-                                        mir: &Mir,
-                                        w: &mut W) -> io::Result<()>
+pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
+                                      nodeid: NodeId,
+                                      mir: &Mir,
+                                      w: &mut W) -> io::Result<()>
     where W: Write
 {
     writeln!(w, "digraph Mir_{} {{", nodeid)?;
@@ -137,11 +137,11 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result
 /// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
 /// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
 /// all the variables and temporaries.
-fn write_graph_label<'a, 'tcx, W: Write>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                         nid: NodeId,
-                                         mir: &Mir,
-                                         w: &mut W)
-                                         -> io::Result<()> {
+fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                               nid: NodeId,
+                                               mir: &Mir,
+                                               w: &mut W)
+                                               -> io::Result<()> {
     write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
 
     // fn argument types.
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 1424c063d73..7658e49ea5e 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -35,48 +35,235 @@
 
 use rustc::mir::*;
 use rustc::mir::visit::{LvalueContext, Visitor};
-use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::indexed_set::IdxSetBuf;
-use util::pretty::{write_basic_block, dump_enabled, write_mir_intro};
+use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
 use rustc::mir::transform::MirSource;
 use rustc::ty::item_path;
-use std::path::{PathBuf, Path};
+use std::path::{Path, PathBuf};
 use std::fs;
 use rustc::ty::TyCtxt;
 use std::io::{self, Write};
 
 pub type LocalSet = IdxSetBuf<Local>;
 
+/// This gives the result of the liveness analysis at the boundary of
+/// basic blocks. You can use `simulate_block` to obtain the
+/// intra-block results.
+pub struct LivenessResult {
+    /// Liveness mode in use when these results were computed.
+    pub mode: LivenessMode,
+
+    /// Live variables on entry to each basic block.
+    pub ins: IndexVec<BasicBlock, LocalSet>,
+
+    /// Live variables on exit to each basic block. This is equal to
+    /// the union of the `ins` for each successor.
+    pub outs: IndexVec<BasicBlock, LocalSet>,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct LivenessMode {
+    /// If true, then we will consider "regular uses" of a variable to be live.
+    /// For example, if the user writes `foo(x)`, then this is a regular use of
+    /// the variable `x`.
+    pub include_regular_use: bool,
+
+    /// If true, then we will consider (implicit) drops of a variable
+    /// to be live.  For example, if the user writes `{ let x =
+    /// vec![...]; .. }`, then the drop at the end of the block is an
+    /// implicit drop.
+    ///
+    /// NB. Despite its name, a call like `::std::mem::drop(x)` is
+    /// **not** considered a drop for this purposes, but rather a
+    /// regular use.
+    pub include_drops: bool,
+}
+
+/// Compute which local variables are live within the given function
+/// `mir`. The liveness mode `mode` determines what sorts of uses are
+/// considered to make a variable live (e.g., do drops count?).
+pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult {
+    let locals = mir.local_decls.len();
+    let def_use: IndexVec<_, _> = mir.basic_blocks()
+        .iter()
+        .map(|b| block(mode, b, locals))
+        .collect();
+
+    let mut ins: IndexVec<_, _> = mir.basic_blocks()
+        .indices()
+        .map(|_| LocalSet::new_empty(locals))
+        .collect();
+    let mut outs = ins.clone();
+
+    let mut changed = true;
+    let mut bits = LocalSet::new_empty(locals);
+    while changed {
+        changed = false;
+
+        for b in mir.basic_blocks().indices().rev() {
+            // outs[b] = ∪ {ins of successors}
+            bits.clear();
+            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
+                bits.union(&ins[successor]);
+            }
+            outs[b].clone_from(&bits);
+
+            // bits = use ∪ (bits - def)
+            def_use[b].apply(&mut bits);
+
+            // update bits on entry and flag if they have changed
+            if ins[b] != bits {
+                ins[b].clone_from(&bits);
+                changed = true;
+            }
+        }
+    }
+
+    LivenessResult { mode, ins, outs }
+}
+
+impl LivenessResult {
+    /// Walks backwards through the statements/terminator in the given
+    /// basic block `block`.  At each point within `block`, invokes
+    /// the callback `op` with the current location and the set of
+    /// variables that are live on entry to that location.
+    pub fn simulate_block<'tcx, OP>(&self, mir: &Mir<'tcx>, block: BasicBlock, mut callback: OP)
+    where
+        OP: FnMut(Location, &LocalSet),
+    {
+        let data = &mir[block];
+
+        // Get a copy of the bits on exit from the block.
+        let mut bits = self.outs[block].clone();
+
+        // Start with the maximal statement index -- i.e., right before
+        // the terminator executes.
+        let mut statement_index = data.statements.len();
+
+        // Compute liveness right before terminator and invoke callback.
+        let terminator_location = Location {
+            block,
+            statement_index,
+        };
+        let terminator_defs_uses = self.defs_uses(mir, terminator_location, &data.terminator);
+        terminator_defs_uses.apply(&mut bits);
+        callback(terminator_location, &bits);
+
+        // Compute liveness before each statement (in rev order) and invoke callback.
+        for statement in data.statements.iter().rev() {
+            statement_index -= 1;
+            let statement_location = Location {
+                block,
+                statement_index,
+            };
+            let statement_defs_uses = self.defs_uses(mir, statement_location, statement);
+            statement_defs_uses.apply(&mut bits);
+            callback(statement_location, &bits);
+        }
+
+        assert_eq!(bits, self.ins[block]);
+    }
+
+    fn defs_uses<'tcx, V>(&self, mir: &Mir<'tcx>, location: Location, thing: &V) -> DefsUses
+    where
+        V: MirVisitable<'tcx>,
+    {
+        let locals = mir.local_decls.len();
+        let mut visitor = DefsUsesVisitor {
+            mode: self.mode,
+            defs_uses: DefsUses {
+                defs: LocalSet::new_empty(locals),
+                uses: LocalSet::new_empty(locals),
+            },
+        };
+
+        // Visit the various parts of the basic block in reverse. If we go
+        // forward, the logic in `add_def` and `add_use` would be wrong.
+        thing.apply(location, &mut visitor);
+
+        visitor.defs_uses
+    }
+}
+
+struct DefsUsesVisitor {
+    mode: LivenessMode,
+    defs_uses: DefsUses,
+}
+
 #[derive(Eq, PartialEq, Clone)]
-struct BlockInfo {
+struct DefsUses {
     defs: LocalSet,
     uses: LocalSet,
 }
 
-struct BlockInfoVisitor {
-    pre_defs: LocalSet,
-    defs: LocalSet,
-    uses: LocalSet,
+impl DefsUses {
+    fn apply(&self, bits: &mut LocalSet) -> bool {
+        bits.subtract(&self.defs) | bits.union(&self.uses)
+    }
+
+    fn add_def(&mut self, index: Local) {
+        // If it was used already in the block, remove that use
+        // now that we found a definition.
+        //
+        // Example:
+        //
+        //     // Defs = {X}, Uses = {}
+        //     X = 5
+        //     // Defs = {}, Uses = {X}
+        //     use(X)
+        self.uses.remove(&index);
+        self.defs.add(&index);
+    }
+
+    fn add_use(&mut self, index: Local) {
+        // Inverse of above.
+        //
+        // Example:
+        //
+        //     // Defs = {}, Uses = {X}
+        //     use(X)
+        //     // Defs = {X}, Uses = {}
+        //     X = 5
+        //     // Defs = {}, Uses = {X}
+        //     use(X)
+        self.defs.remove(&index);
+        self.uses.add(&index);
+    }
 }
 
-impl<'tcx> Visitor<'tcx> for BlockInfoVisitor {
-    fn visit_local(&mut self,
-                   &local: &Local,
-                   context: LvalueContext<'tcx>,
-                   _: Location) {
+impl<'tcx> Visitor<'tcx> for DefsUsesVisitor {
+    fn visit_local(&mut self, &local: &Local, context: LvalueContext<'tcx>, _: Location) {
         match context {
+            ///////////////////////////////////////////////////////////////////////////
+            // DEFS
+
             LvalueContext::Store |
 
-            // We let Call defined the result in both the success and unwind cases.
-            // This may not be right.
+            // We let Call define the result in both the success and
+            // unwind cases. This is not really correct, however it
+            // does not seem to be observable due to the way that we
+            // generate MIR. See the test case
+            // `mir-opt/nll/liveness-call-subtlety.rs`. To do things
+            // properly, we would apply the def in call only to the
+            // input from the success path and not the unwind
+            // path. -nmatsakis
             LvalueContext::Call |
 
             // Storage live and storage dead aren't proper defines, but we can ignore
             // values that come before them.
             LvalueContext::StorageLive |
             LvalueContext::StorageDead => {
-                self.defs.add(&local);
+                self.defs_uses.add_def(local);
             }
+
+            ///////////////////////////////////////////////////////////////////////////
+            // REGULAR USES
+            //
+            // These are uses that occur *outside* of a drop. For the
+            // purposes of NLL, these are special in that **all** the
+            // lifetimes appearing in the variable must be live for each regular use.
+
             LvalueContext::Projection(..) |
 
             // Borrows only consider their local used at the point of the borrow.
@@ -87,124 +274,108 @@ impl<'tcx> Visitor<'tcx> for BlockInfoVisitor {
 
             LvalueContext::Inspect |
             LvalueContext::Consume |
-            LvalueContext::Validate |
+            LvalueContext::Validate => {
+                if self.mode.include_regular_use {
+                    self.defs_uses.add_use(local);
+                }
+            }
+
+            ///////////////////////////////////////////////////////////////////////////
+            // DROP USES
+            //
+            // These are uses that occur in a DROP (a MIR drop, not a
+            // call to `std::mem::drop()`). For the purposes of NLL,
+            // uses in drop are special because `#[may_dangle]`
+            // attributes can affect whether lifetimes must be live.
 
-            // We consider drops to always be uses of locals.
-            // Drop eloboration should be run before this analysis otherwise
-            // the results might be too pessimistic.
             LvalueContext::Drop => {
-                // Ignore uses which are already defined in this block
-                if !self.pre_defs.contains(&local) {
-                    self.uses.add(&local);
+                if self.mode.include_drops {
+                    self.defs_uses.add_use(local);
                 }
             }
         }
     }
 }
 
-fn block<'tcx>(b: &BasicBlockData<'tcx>, locals: usize) -> BlockInfo {
-    let mut visitor = BlockInfoVisitor {
-        pre_defs: LocalSet::new_empty(locals),
-        defs: LocalSet::new_empty(locals),
-        uses: LocalSet::new_empty(locals),
+fn block<'tcx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses {
+    let mut visitor = DefsUsesVisitor {
+        mode,
+        defs_uses: DefsUses {
+            defs: LocalSet::new_empty(locals),
+            uses: LocalSet::new_empty(locals),
+        },
     };
 
-    let dummy_location = Location { block: BasicBlock::new(0), statement_index: 0 };
+    let dummy_location = Location {
+        block: BasicBlock::new(0),
+        statement_index: 0,
+    };
 
-    for statement in &b.statements {
+    // Visit the various parts of the basic block in reverse. If we go
+    // forward, the logic in `add_def` and `add_use` would be wrong.
+    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
+    for statement in b.statements.iter().rev() {
         visitor.visit_statement(BasicBlock::new(0), statement, dummy_location);
-        visitor.pre_defs.union(&visitor.defs);
     }
-    visitor.visit_terminator(BasicBlock::new(0), b.terminator(), dummy_location);
 
-    BlockInfo {
-        defs: visitor.defs,
-        uses: visitor.uses,
-    }
+    visitor.defs_uses
 }
 
-// This gives the result of the liveness analysis at the boundary of basic blocks
-pub struct LivenessResult {
-    pub ins: IndexVec<BasicBlock, LocalSet>,
-    pub outs: IndexVec<BasicBlock, LocalSet>,
+trait MirVisitable<'tcx> {
+    fn apply<V>(&self, location: Location, visitor: &mut V)
+    where
+        V: Visitor<'tcx>;
 }
 
-pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>) -> LivenessResult {
-    let locals = mir.local_decls.len();
-    let def_use: IndexVec<_, _> = mir.basic_blocks().iter().map(|b| {
-        block(b, locals)
-    }).collect();
-
-    let copy = |from: &IndexVec<BasicBlock, LocalSet>, to: &mut IndexVec<BasicBlock, LocalSet>| {
-        for (i, set) in to.iter_enumerated_mut() {
-            set.clone_from(&from[i]);
-        }
-    };
-
-    let mut ins: IndexVec<_, _> = mir.basic_blocks()
-        .indices()
-        .map(|_| LocalSet::new_empty(locals)).collect();
-    let mut outs = ins.clone();
-
-    let mut ins_ = ins.clone();
-    let mut outs_ = outs.clone();
-
-    loop {
-        copy(&ins, &mut ins_);
-        copy(&outs, &mut outs_);
-
-        for b in mir.basic_blocks().indices().rev() {
-            // out = ∪ {ins of successors}
-            outs[b].clear();
-            for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() {
-                outs[b].union(&ins[successor]);
-            }
-
-            // in = use ∪ (out - def)
-            ins[b].clone_from(&outs[b]);
-            ins[b].subtract(&def_use[b].defs);
-            ins[b].union(&def_use[b].uses);
-        }
-
-        if ins_ == ins && outs_ == outs {
-            break;
-        }
+impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
+    fn apply<V>(&self, location: Location, visitor: &mut V)
+    where
+        V: Visitor<'tcx>,
+    {
+        visitor.visit_statement(location.block, self, location)
     }
+}
 
-    LivenessResult {
-        ins,
-        outs,
+impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
+    fn apply<V>(&self, location: Location, visitor: &mut V)
+    where
+        V: Visitor<'tcx>,
+    {
+        visitor.visit_terminator(location.block, self.as_ref().unwrap(), location)
     }
 }
 
-pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          pass_name: &str,
-                          source: MirSource,
-                          mir: &Mir<'tcx>,
-                          result: &LivenessResult) {
+pub fn dump_mir<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pass_name: &str,
+    source: MirSource,
+    mir: &Mir<'tcx>,
+    result: &LivenessResult,
+) {
     if !dump_enabled(tcx, pass_name, source) {
         return;
     }
-    let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
+    let node_path = item_path::with_forced_impl_filename_line(|| {
+        // see notes on #41697 below
         tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
     });
-    dump_matched_mir_node(tcx, pass_name, &node_path,
-                          source, mir, result);
+    dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result);
 }
 
-fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   pass_name: &str,
-                                   node_path: &str,
-                                   source: MirSource,
-                                   mir: &Mir<'tcx>,
-                                   result: &LivenessResult) {
+fn dump_matched_mir_node<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pass_name: &str,
+    node_path: &str,
+    source: MirSource,
+    mir: &Mir<'tcx>,
+    result: &LivenessResult,
+) {
     let mut file_path = PathBuf::new();
     if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
         let p = Path::new(file_dir);
         file_path.push(p);
     };
-    let file_name = format!("rustc.node{}{}-liveness.mir",
-                            source.item_id(), pass_name);
+    let file_name = format!("rustc.node{}{}-liveness.mir", source.item_id(), pass_name);
     file_path.push(&file_name);
     let _ = fs::File::create(&file_path).and_then(|mut file| {
         writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
@@ -216,16 +387,18 @@ fn dump_matched_mir_node<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     });
 }
 
-pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              src: MirSource,
-                              mir: &Mir<'tcx>,
-                              w: &mut Write,
-                              result: &LivenessResult)
-                              -> io::Result<()> {
+pub fn write_mir_fn<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    src: MirSource,
+    mir: &Mir<'tcx>,
+    w: &mut Write,
+    result: &LivenessResult,
+) -> io::Result<()> {
     write_mir_intro(tcx, src, mir, w)?;
     for block in mir.basic_blocks().indices() {
         let print = |w: &mut Write, prefix, result: &IndexVec<BasicBlock, LocalSet>| {
-            let live: Vec<String> = mir.local_decls.indices()
+            let live: Vec<String> = mir.local_decls
+                .indices()
                 .filter(|i| result[block].contains(i))
                 .map(|i| format!("{:?}", i))
                 .collect();
@@ -242,4 +415,3 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     writeln!(w, "}}")?;
     Ok(())
 }
-
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 9f61feabe41..1d924175b21 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -56,13 +56,13 @@ pub enum PassWhere {
 /// - `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.
-pub fn dump_mir<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             pass_num: Option<(MirSuite, MirPassIndex)>,
-                             pass_name: &str,
-                             disambiguator: &Display,
-                             source: MirSource,
-                             mir: &Mir<'tcx>,
-                             extra_data: F)
+pub fn dump_mir<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                   pass_num: Option<(MirSuite, MirPassIndex)>,
+                                   pass_name: &str,
+                                   disambiguator: &Display,
+                                   source: MirSource,
+                                   mir: &Mir<'tcx>,
+                                   extra_data: F)
 where
     F: FnMut(PassWhere, &mut Write) -> io::Result<()>
 {
@@ -77,10 +77,10 @@ where
                           disambiguator, source, mir, extra_data);
 }
 
-pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              pass_name: &str,
-                              source: MirSource)
-                              -> bool {
+pub fn dump_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                    pass_name: &str,
+                                    source: MirSource)
+                                    -> bool {
     let filters = match tcx.sess.opts.debugging_opts.dump_mir {
         None => return false,
         Some(ref filters) => filters,
@@ -101,14 +101,14 @@ pub fn dump_enabled<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 // `item_path_str()` would otherwise trigger `type_of`, and this can
 // run while we are already attempting to evaluate `type_of`.
 
-fn dump_matched_mir_node<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      pass_num: Option<(MirSuite, MirPassIndex)>,
-                                      pass_name: &str,
-                                      node_path: &str,
-                                      disambiguator: &Display,
-                                      source: MirSource,
-                                      mir: &Mir<'tcx>,
-                                      mut extra_data: F)
+fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                            pass_num: Option<(MirSuite, MirPassIndex)>,
+                                            pass_name: &str,
+                                            node_path: &str,
+                                            disambiguator: &Display,
+                                            source: MirSource,
+                                            mir: &Mir<'tcx>,
+                                            mut extra_data: F)
 where
     F: FnMut(PassWhere, &mut Write) -> io::Result<()>
 {
@@ -161,10 +161,10 @@ where
 }
 
 /// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  single: Option<DefId>,
-                                  w: &mut Write)
-                                  -> io::Result<()>
+pub fn write_mir_pretty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                        single: Option<DefId>,
+                                        w: &mut Write)
+                                        -> io::Result<()>
 {
     writeln!(w, "// WARNING: This output format is intended for human consumers only")?;
     writeln!(w, "// and is subject to change without notice. Knock yourself out.")?;
@@ -192,12 +192,12 @@ pub fn write_mir_pretty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Ok(())
 }
 
-pub fn write_mir_fn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 src: MirSource,
-                                 mir: &Mir<'tcx>,
-                                 extra_data: &mut F,
-                                 w: &mut Write)
-                                 -> io::Result<()>
+pub fn write_mir_fn<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                       src: MirSource,
+                                       mir: &Mir<'tcx>,
+                                       extra_data: &mut F,
+                                       w: &mut Write)
+                                       -> io::Result<()>
 where
     F: FnMut(PassWhere, &mut Write) -> io::Result<()>
 {
@@ -321,11 +321,11 @@ fn write_scope_tree(tcx: TyCtxt,
 
 /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
 /// local variables (both user-defined bindings and compiler temporaries).
-pub fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             src: MirSource,
-                             mir: &Mir,
-                             w: &mut Write)
-                             -> io::Result<()> {
+pub fn write_mir_intro<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                       src: MirSource,
+                                       mir: &Mir,
+                                       w: &mut Write)
+                                       -> io::Result<()> {
     write_mir_sig(tcx, src, mir, w)?;
     writeln!(w, " {{")?;
 
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index e44f3f39824..6d9c2948841 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -42,6 +42,15 @@ impl<'a> AstValidator<'a> {
         }
     }
 
+    fn invalid_non_exhaustive_attribute(&self, variant: &Variant) {
+        let has_non_exhaustive = variant.node.attrs.iter()
+            .any(|attr| attr.check_name("non_exhaustive"));
+        if has_non_exhaustive {
+            self.err_handler().span_err(variant.span,
+                                        "#[non_exhaustive] is not yet supported on variants");
+        }
+    }
+
     fn invalid_visibility(&self, vis: &Visibility, span: Span, note: Option<&str>) {
         if vis != &Visibility::Inherited {
             let mut err = struct_span_err!(self.session,
@@ -213,7 +222,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                                         item.span,
                                         Some("place qualifiers on individual impl items instead"));
             }
-            ItemKind::DefaultImpl(..) => {
+            ItemKind::AutoImpl(..) => {
                 self.invalid_visibility(&item.vis, item.span, None);
             }
             ItemKind::ForeignMod(..) => {
@@ -224,12 +233,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
+                    self.invalid_non_exhaustive_attribute(variant);
                     for field in variant.node.data.fields() {
                         self.invalid_visibility(&field.vis, field.span, None);
                     }
                 }
             }
-            ItemKind::Trait(.., ref bounds, ref trait_items) => {
+            ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
+                if is_auto == IsAuto::Yes {
+                    // Auto traits cannot have generics, super traits nor contain items.
+                    if !generics.ty_params.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot have generics");
+                    }
+                    if !bounds.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot have super traits");
+                    }
+                    if !trait_items.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot contain items");
+                    }
+                }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
                 for trait_item in trait_items {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 1fa49614580..ab41ad1e099 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -14,7 +14,7 @@
 
 use rustc_const_math::{ConstUsize};
 use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
-use rustc::mir::{Constant, Literal, Location, LocalDecl};
+use rustc::mir::{Constant, Literal, Location, Local, LocalDecl};
 use rustc::mir::{Lvalue, LvalueElem, LvalueProjection};
 use rustc::mir::{Mir, Operand, ProjectionElem};
 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
@@ -121,6 +121,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
             TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
             TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
             TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
+            TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
         }, kind);
         self.super_terminator_kind(block, kind, location);
     }
@@ -269,9 +270,10 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
     }
 
     fn visit_local_decl(&mut self,
+                        local: Local,
                         local_decl: &LocalDecl<'tcx>) {
         self.record("LocalDecl", local_decl);
-        self.super_local_decl(local_decl);
+        self.super_local_decl(local, local_decl);
     }
 
     fn visit_visibility_scope(&mut self,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 3beba03ee14..630260feed7 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -147,7 +147,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
                 let def_id = self.tcx.hir.local_def_id(item.id);
                 cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
             }
-            hir::ItemDefaultImpl(..) => {
+            hir::ItemAutoImpl(..) => {
                 let def_id = self.tcx.hir.local_def_id(item.id);
                 self.impl_trait_level(def_id)
             }
@@ -213,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             }
             hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
             hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
-            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
+            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
         }
 
         // Mark all items in interfaces of reachable items as reachable
@@ -225,7 +225,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             // Reexports are handled in visit_mod
             hir::ItemUse(..) => {}
             // The interface is empty
-            hir::ItemDefaultImpl(..) => {}
+            hir::ItemAutoImpl(..) => {}
             // The interface is empty
             hir::ItemGlobalAsm(..) => {}
             // Visit everything
@@ -627,6 +627,16 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
                                 ctor_vis = field_vis;
                             }
                         }
+
+                        // If the structure is marked as non_exhaustive then lower the
+                        // visibility to within the crate.
+                        let struct_def_id = self.tcx.hir.get_parent_did(node_id);
+                        let adt_def = self.tcx.adt_def(struct_def_id);
+                        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+                            ctor_vis = ty::Visibility::Restricted(
+                                DefId::local(CRATE_DEF_INDEX));
+                        }
+
                         return ctor_vis;
                     }
                     node => bug!("unexpected node kind: {:?}", node)
@@ -1504,7 +1514,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                 }
             }
             // The interface is empty
-            hir::ItemDefaultImpl(..) => {}
+            hir::ItemAutoImpl(..) => {}
             // An inherent impl is public when its type is public
             // Subitems of inherent impls have their own publicity
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index 0968ea31b75..ab2d152b724 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -16,3 +16,4 @@ rustc = { path = "../librustc" }
 arena = { path = "../libarena" }
 rustc_errors = { path = "../librustc_errors" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 880b370c7f6..a10bce29342 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -338,11 +338,22 @@ impl<'a> Resolver<'a> {
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref struct_def, _) => {
                 // Define a name in the type namespace.
-                let def = Def::Struct(self.definitions.local_def_id(item.id));
+                let def_id = self.definitions.local_def_id(item.id);
+                let def = Def::Struct(def_id);
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
 
-                // Record field names for error reporting.
                 let mut ctor_vis = vis;
+
+                let has_non_exhaustive = item.attrs.iter()
+                    .any(|item| item.check_name("non_exhaustive"));
+
+                // If the structure is marked as non_exhaustive then lower the visibility
+                // to within the crate.
+                if has_non_exhaustive && vis == ty::Visibility::Public {
+                    ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+                }
+
+                // Record field names for error reporting.
                 let field_names = struct_def.fields().iter().filter_map(|field| {
                     let field_vis = self.resolve_visibility(&field.vis);
                     if ctor_vis.is_at_least(field_vis, &*self) {
@@ -376,7 +387,7 @@ impl<'a> Resolver<'a> {
                 self.insert_field_names(item_def_id, field_names);
             }
 
-            ItemKind::DefaultImpl(..) | ItemKind::Impl(..) => {}
+            ItemKind::AutoImpl(..) | ItemKind::Impl(..) => {}
 
             ItemKind::Trait(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
@@ -414,6 +425,7 @@ impl<'a> Resolver<'a> {
         // value namespace, they are reserved for possible future use.
         let ctor_kind = CtorKind::from_ast(&variant.node.data);
         let ctor_def = Def::VariantCtor(def_id, ctor_kind);
+
         self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
     }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3b27890013a..f3d4e0a7848 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -24,6 +24,7 @@ extern crate rustc_errors as errors;
 extern crate arena;
 #[macro_use]
 extern crate rustc;
+extern crate rustc_data_structures;
 
 use self::Namespace::*;
 use self::TypeParameters::*;
@@ -59,7 +60,7 @@ use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
 use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -223,7 +224,11 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let target_sp = binding_error.target.iter().map(|x| *x).collect::<Vec<_>>();
             let msp = MultiSpan::from_spans(target_sp.clone());
             let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
-            let mut err = resolver.session.struct_span_err_with_code(msp, &msg, "E0408");
+            let mut err = resolver.session.struct_span_err_with_code(
+                msp,
+                &msg,
+                DiagnosticId::Error("E0408".into()),
+            );
             for sp in target_sp {
                 err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
             }
@@ -1841,7 +1846,7 @@ impl<'a> Resolver<'a> {
                                              |this| visit::walk_item(this, item));
             }
 
-            ItemKind::DefaultImpl(_, ref trait_ref) => {
+            ItemKind::AutoImpl(_, ref trait_ref) => {
                 self.with_optional_trait_ref(Some(trait_ref), |this, _| {
                     // Resolve type arguments in trait path
                     visit::walk_trait_ref(this, trait_ref);
@@ -1854,7 +1859,7 @@ impl<'a> Resolver<'a> {
                                             item.id,
                                             impl_items),
 
-            ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
+            ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
                     let local_def_id = this.definitions.local_def_id(item.id);
@@ -2490,18 +2495,19 @@ impl<'a> Resolver<'a> {
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
                  format!("not found in {}", mod_str), item_span)
             };
+            let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
 
             // Emit special messages for unresolved `Self` and `self`.
             if is_self_type(path, ns) {
                 __diagnostic_used!(E0411);
-                err.code("E0411".into());
+                err.code(DiagnosticId::Error("E0411".into()));
                 err.span_label(span, "`Self` is only available in traits and impls");
                 return (err, Vec::new());
             }
             if is_self_value(path, ns) {
                 __diagnostic_used!(E0424);
-                err.code("E0424".into());
+                err.code(DiagnosticId::Error("E0424".into()));
                 err.span_label(span, format!("`self` value is only available in \
                                                methods with `self` parameter"));
                 return (err, Vec::new());
@@ -2597,7 +2603,7 @@ impl<'a> Resolver<'a> {
                             }
                         }
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
-                                                       path_str));
+                                                     path_str));
                         return (err, candidates);
                     }
                     _ => {}
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 064032b8884..a52e6fcad14 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -13,6 +13,7 @@ use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use resolve_imports::ImportResolver;
+use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index 12897050164..1b5ab10fc70 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -15,7 +15,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rls-data = "0.11"
+rls-data = "0.12"
 rls-span = "0.4"
 # FIXME(#40527) should move rustc serialize out of tree
 rustc-serialize = "0.3"
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 4eac4398c18..d190ae1431f 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -46,8 +46,8 @@ use json_dumper::{JsonDumper, DumpOutput};
 use span_utils::SpanUtils;
 use sig;
 
-use rls_data::{CratePreludeData, Import, ImportKind, SpanData, Ref, RefKind,
-               Def, DefKind, Relation, RelationKind};
+use rls_data::{CratePreludeData, GlobalCrateId, Import, ImportKind, SpanData,
+               Ref, RefKind, Def, DefKind, Relation, RelationKind};
 
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
@@ -131,7 +131,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         });
 
         let data = CratePreludeData {
-            crate_name: name.into(),
+            crate_id: GlobalCrateId {
+                name: name.into(),
+                disambiguator: self.tcx.sess.local_crate_disambiguator()
+                                   .to_fingerprint().as_value(),
+            },
             crate_root: crate_root.unwrap_or("<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
             span: self.span_from_span(krate.span),
@@ -318,16 +322,15 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             let mut collector = PathCollector::new();
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
-            for &(id, ref p, ..) in &collector.collected_paths {
+
+            for (id, i, sp, ..) in collector.collected_idents {
                 let hir_id = self.tcx.hir.node_to_hir_id(id);
                 let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
-                // get the span only for the name of the variable (I hope the path is only ever a
-                // variable name, but who knows?)
-                let sub_span = span_utils.span_for_last_ident(p.span);
-                if !self.span.filter_generated(sub_span, p.span) {
+                let sub_span = span_utils.span_for_last_ident(sp);
+                if !self.span.filter_generated(sub_span, sp) {
                     let id = ::id_from_node_id(id, &self.save_ctxt);
                     let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -335,8 +338,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                         kind: DefKind::Local,
                         id,
                         span,
-                        name: path_to_string(p),
-                        qualname: format!("{}::{}", qualname, path_to_string(p)),
+                        name: i.to_string(),
+                        qualname: format!("{}::{}", qualname, i.to_string()),
                         value: typ,
                         parent: None,
                         children: vec![],
@@ -391,14 +394,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         }
     }
 
-    fn process_trait_ref(&mut self, trait_ref: &'l ast::TraitRef) {
-        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref);
-        if let Some(trait_ref_data) = trait_ref_data {
-            self.dumper.dump_ref(trait_ref_data);
-        }
-        self.process_path(trait_ref.ref_id, &trait_ref.path);
-    }
-
     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
         let field_data = self.save_ctxt.get_field_data(field, parent_id);
         if let Some(field_data) = field_data {
@@ -526,36 +521,43 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                       item: &'l ast::Item,
                       def: &'l ast::VariantData,
                       ty_params: &'l ast::Generics) {
+        debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
-        let (value, fields) =
-            if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node
-        {
-            let include_priv_fields = !self.save_ctxt.config.pub_only;
-            let fields_str = fields
-                .iter()
-                .enumerate()
-                .filter_map(|(i, f)| {
-                     if include_priv_fields || f.vis == ast::Visibility::Public {
-                         f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
-                     } else {
-                         None
-                     }
-                })
-                .collect::<Vec<_>>()
-                .join(", ");
-            let value = format!("{} {{ {} }}", name, fields_str);
-            (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
-        } else {
-            (String::new(), vec![])
+        let (kind, keyword) = match item.node {
+            ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct),
+            ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union),
+            _ => unreachable!(),
+        };
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
+        let (value, fields) = match item.node {
+            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
+            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
+                let include_priv_fields = !self.save_ctxt.config.pub_only;
+                let fields_str = fields
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(i, f)| {
+                         if include_priv_fields || f.vis == ast::Visibility::Public {
+                             f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
+                         } else {
+                             None
+                         }
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                let value = format!("{} {{ {} }}", name, fields_str);
+                (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
+            }
+            _ => (String::new(), vec![])
         };
 
         if !self.span.filter_generated(sub_span, item.span) {
             let span = self.span_from_span(sub_span.expect("No span found for struct"));
             self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                kind: DefKind::Struct,
+                kind,
                 id: ::id_from_node_id(item.id, &self.save_ctxt),
                 span,
                 name,
@@ -783,7 +785,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         }
     }
 
-    fn process_path(&mut self, id: NodeId, path: &ast::Path) {
+    fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
+        debug!("process_path {:?}", path);
         let path_data = self.save_ctxt.get_path_data(id, path);
         if generated_code(path.span) && path_data.is_none() {
             return;
@@ -798,6 +801,27 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
 
         self.dumper.dump_ref(path_data);
 
+        // Type parameters
+        for seg in &path.segments {
+            if let Some(ref params) = seg.parameters {
+                match **params {
+                    ast::PathParameters::AngleBracketed(ref data) => {
+                        for t in &data.types {
+                            self.visit_ty(t);
+                        }
+                    }
+                    ast::PathParameters::Parenthesized(ref data) => {
+                        for t in &data.inputs {
+                            self.visit_ty(t);
+                        }
+                        if let Some(ref t) = data.output {
+                            self.visit_ty(t);
+                        }
+                    }
+                }
+            }
+        }
+
         // Modules or types in the path prefix.
         match self.save_ctxt.get_path_def(id) {
             HirDef::Method(did) => {
@@ -850,7 +874,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         walk_list!(self, visit_expr, base);
     }
 
-    fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P<ast::Expr>]) {
+    fn process_method_call(&mut self,
+                           ex: &'l ast::Expr,
+                           seg: &'l ast::PathSegment,
+                           args: &'l [P<ast::Expr>]) {
+        debug!("process_method_call {:?} {:?}", ex, ex.span);
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
             down_cast_data!(mcd, RefData, ex.span);
             if !generated_code(ex.span) {
@@ -858,6 +886,15 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
             }
         }
 
+        // Explicit types in the turbo-fish.
+        if let Some(ref params) = seg.parameters {
+            if let ast::PathParameters::AngleBracketed(ref data) = **params {
+                for t in &data.types {
+                    self.visit_ty(t);
+                }
+            }
+        }
+
         // walk receiver and args
         walk_list!(self, visit_expr, args);
     }
@@ -904,7 +941,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         collector.visit_pat(&p);
         self.visit_pat(&p);
 
-        for &(id, ref p, immut) in &collector.collected_paths {
+        for (id, i, sp, immut) in collector.collected_idents {
             let mut value = match immut {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
@@ -924,10 +961,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
 
             // Get the span only for the name of the variable (I hope the path
             // is only ever a variable name, but who knows?).
-            let sub_span = self.span.span_for_last_ident(p.span);
+            let sub_span = self.span.span_for_last_ident(sp);
             // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            if !self.span.filter_generated(sub_span, p.span) {
-                let qualname = format!("{}${}", path_to_string(p), id);
+            if !self.span.filter_generated(sub_span, sp) {
+                let qualname = format!("{}${}", i.to_string(), id);
                 let id = ::id_from_node_id(id, &self.save_ctxt);
                 let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -935,7 +972,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                     kind: DefKind::Local,
                     id,
                     span,
-                    name: path_to_string(p),
+                    name: i.to_string(),
                     qualname,
                     value: typ,
                     parent: None,
@@ -1212,7 +1249,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 self.process_static_or_const_item(item, typ, expr),
             Const(ref typ, ref expr) =>
                 self.process_static_or_const_item(item, &typ, &expr),
-            Struct(ref def, ref ty_params) => self.process_struct(item, def, ty_params),
+            Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
+                self.process_struct(item, def, ty_params)
+            }
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             Impl(..,
                  ref ty_params,
@@ -1221,7 +1260,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                  ref impl_items) => {
                 self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
             }
-            Trait(_, ref generics, ref trait_refs, ref methods) =>
+            Trait(_, _, ref generics, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
             Mod(ref m) => {
                 self.process_mod(item);
@@ -1263,7 +1302,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
         for param in generics.ty_params.iter() {
             for bound in param.bounds.iter() {
                 if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
-                    self.process_trait_ref(&trait_ref.trait_ref);
+                    self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
                 }
             }
             if let Some(ref ty) = param.default {
@@ -1318,7 +1357,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 let def = self.save_ctxt.get_path_def(hir_expr.id);
                 self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
             }
-            ast::ExprKind::MethodCall(.., ref args) => self.process_method_call(ex, args),
+            ast::ExprKind::MethodCall(ref seg, ref args) => self.process_method_call(ex, seg, args),
             ast::ExprKind::Field(ref sub_ex, _) => {
                 self.visit_expr(&sub_ex);
 
@@ -1390,15 +1429,15 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
-                visit::walk_expr(self, subexpression);
+                self.visit_expr(subexpression);
                 visit::walk_block(self, block);
             }
             ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
                 let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
-                visit::walk_expr(self, subexpression);
+                self.visit_expr(subexpression);
                 visit::walk_block(self, block);
-                opt_else.as_ref().map(|el| visit::walk_expr(self, el));
+                opt_else.as_ref().map(|el| self.visit_expr(el));
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
                 self.visit_expr(element);
@@ -1430,15 +1469,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
             self.visit_pat(&pattern);
         }
 
-        // This is to get around borrow checking, because we need mut self to call process_path.
-        let mut paths_to_process = vec![];
-
         // process collected paths
-        for &(id, ref p, immut) in &collector.collected_paths {
+        for (id, i, sp, immut) in collector.collected_idents {
             match self.save_ctxt.get_path_def(id) {
                 HirDef::Local(id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(p.span).to_string()
+                        self.span.snippet(sp).to_string()
                     } else {
                         "<mutable>".to_string()
                     };
@@ -1451,18 +1487,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                     value.push_str(": ");
                     value.push_str(&typ);
 
-                    assert!(p.segments.len() == 1,
-                            "qualified path for local variable def in arm");
-                    if !self.span.filter_generated(Some(p.span), p.span) {
-                        let qualname = format!("{}${}", path_to_string(p), id);
+                    if !self.span.filter_generated(Some(sp), sp) {
+                        let qualname = format!("{}${}", i.to_string(), id);
                         let id = ::id_from_node_id(id, &self.save_ctxt);
-                        let span = self.span_from_span(p.span);
+                        let span = self.span_from_span(sp);
 
                         self.dumper.dump_def(false, Def {
                             kind: DefKind::Local,
                             id,
                             span,
-                            name: path_to_string(p),
+                            name: i.to_string(),
                             qualname,
                             value: typ,
                             parent: None,
@@ -1474,19 +1508,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                         });
                     }
                 }
-                HirDef::StructCtor(..) | HirDef::VariantCtor(..) |
-                HirDef::Const(..) | HirDef::AssociatedConst(..) |
-                HirDef::Struct(..) | HirDef::Variant(..) |
-                HirDef::TyAlias(..) | HirDef::AssociatedTy(..) |
-                HirDef::SelfTy(..) => {
-                    paths_to_process.push((id, p.clone()))
-                }
-                def => error!("unexpected definition kind when processing collected paths: {:?}",
+                def => error!("unexpected definition kind when processing collected idents: {:?}",
                               def),
             }
         }
 
-        for &(id, ref path) in &paths_to_process {
+        for (id, ref path) in collector.collected_paths {
             self.process_path(id, path);
         }
         walk_list!(self, visit_expr, &arm.guard);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index cf2cad1b38c..edb51ae59e1 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -63,7 +63,7 @@ use dump_visitor::DumpVisitor;
 use span_utils::SpanUtils;
 
 use rls_data::{Ref, RefKind, SpanData, MacroRef, Def, DefKind, Relation, RelationKind,
-               ExternalCrateData};
+               ExternalCrateData, GlobalCrateId};
 use rls_data::config::Config;
 
 
@@ -82,10 +82,6 @@ pub enum Data {
     RelationData(Relation),
 }
 
-macro_rules! option_try(
-    ($e:expr) => (match $e { Some(e) => e, None => return None })
-);
-
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     fn span_from_span(&self, span: Span) -> SpanData {
         use rls_span::{Row, Column};
@@ -119,9 +115,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             };
             let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo());
             result.push(ExternalCrateData {
-                name: self.tcx.crate_name(n).to_string(),
-                num: n.as_u32(),
                 file_name: SpanUtils::make_path_string(&lo_loc.file.name),
+                num: n.as_u32(),
+                id: GlobalCrateId {
+                    name: self.tcx.crate_name(n).to_string(),
+                    disambiguator: self.tcx.crate_disambiguator(n)
+                                       .to_fingerprint().as_value(),
+                },
             });
         }
 
@@ -546,16 +546,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     }
                 }
             }
-            ast::ExprKind::MethodCall(..) => {
+            ast::ExprKind::MethodCall(ref seg, ..) => {
                 let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id);
                 let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id();
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
                 };
-                let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
-                filter!(self.span_utils, sub_span, expr.span, None);
-                let span = self.span_from_span(sub_span.unwrap());
+                let sub_span = seg.span;
+                filter!(self.span_utils, Some(sub_span), expr.span, None);
+                let span = self.span_from_span(sub_span);
                 Some(Data::RefData(Ref {
                     kind: RefKind::Function,
                     span,
@@ -579,8 +579,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Node::NodeItem(&hir::Item { node: hir::ItemUse(ref path, _), .. }) |
             Node::NodeVisibility(&hir::Visibility::Restricted { ref path, .. }) => path.def,
 
-            Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
             Node::NodeExpr(&hir::Expr { node: hir::ExprStruct(ref qpath, ..), .. }) |
+            Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => {
@@ -614,13 +614,31 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     }
 
     pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
+        // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
+        fn fn_type(path: &ast::Path) -> bool {
+            if path.segments.len() != 1 {
+                return false;
+            }
+            if let Some(ref params) = path.segments[0].parameters {
+                if let ast::PathParameters::Parenthesized(_) = **params {
+                    return true;
+                }
+            }
+            false
+        }
+
+        if path.segments.is_empty() {
+            return None;
+        }
+
         let def = self.get_path_def(id);
-        let sub_span = self.span_utils.span_for_last_ident(path.span);
-        filter!(self.span_utils, sub_span, path.span, None);
+        let last_seg = &path.segments[path.segments.len() - 1];
+        let sub_span = last_seg.span;
+        filter!(self.span_utils, Some(sub_span), path.span, None);
         match def {
             HirDef::Upvar(id, ..) |
             HirDef::Local(id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
@@ -630,15 +648,24 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             HirDef::Static(..) |
             HirDef::Const(..) |
             HirDef::AssociatedConst(..) |
-            HirDef::StructCtor(..) |
             HirDef::VariantCtor(..) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
                     ref_id: id_from_def_id(def.def_id()),
                 })
             }
+            HirDef::Trait(def_id) if fn_type(path) => {
+                // Function type bounds are desugared in the parser, so we have to
+                // special case them here.
+                let fn_span = self.span_utils.span_for_first_ident(path.span);
+                fn_span.map(|span| Ref {
+                    kind: RefKind::Type,
+                    span: self.span_from_span(span),
+                    ref_id: id_from_def_id(def_id),
+                })
+            }
             HirDef::Struct(def_id) |
             HirDef::Variant(def_id, ..) |
             HirDef::Union(def_id) |
@@ -648,16 +675,26 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             HirDef::AssociatedTy(def_id) |
             HirDef::Trait(def_id) |
             HirDef::TyParam(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Type,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
+            HirDef::StructCtor(def_id, _) => {
+                // This is a reference to a tuple struct where the def_id points
+                // to an invisible constructor function. That is not a very useful
+                // def, so adjust to point to the tuple struct itself.
+                let span = self.span_from_span(sub_span);
+                let parent_def_id = self.tcx.parent_def_id(def_id).unwrap();
+                Some(Ref {
+                    kind: RefKind::Type,
+                    span,
+                    ref_id: id_from_def_id(parent_def_id),
+                })
+            }
             HirDef::Method(decl_id) => {
-                let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
-                filter!(self.span_utils, sub_span, path.span, None);
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
                     self.tcx.associated_items(ti.container.id())
@@ -666,7 +703,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 } else {
                     None
                 };
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Function,
                     span,
@@ -674,7 +711,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 })
             }
             HirDef::Fn(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Function,
                     span,
@@ -682,7 +719,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 })
             }
             HirDef::Mod(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Mod,
                     span,
@@ -728,8 +765,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         // macro uses.
         let callsite = span.source_callsite();
         let callsite_span = self.span_from_span(callsite);
-        let callee = option_try!(span.source_callee());
-        let callee_span = option_try!(callee.span);
+        let callee = span.source_callee()?;
+        let callee_span = callee.span?;
 
         // Ignore attribute macros, their spans are usually mangled
         if let MacroAttribute(_) = callee.format {
@@ -818,29 +855,31 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
     sig
 }
 
-// An AST visitor for collecting paths from patterns.
-struct PathCollector {
-    // The Row field identifies the kind of pattern.
-    collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>,
+// An AST visitor for collecting paths (e.g., the names of structs) and formal
+// variables (idents) from patterns.
+struct PathCollector<'l> {
+    collected_paths: Vec<(NodeId, &'l ast::Path)>,
+    collected_idents: Vec<(NodeId, ast::Ident, Span, ast::Mutability)>,
 }
 
-impl PathCollector {
-    fn new() -> PathCollector {
-        PathCollector { collected_paths: vec![] }
+impl<'l> PathCollector<'l> {
+    fn new() -> PathCollector<'l> {
+        PathCollector {
+            collected_paths: vec![],
+            collected_idents: vec![],
+        }
     }
 }
 
-impl<'a> Visitor<'a> for PathCollector {
-    fn visit_pat(&mut self, p: &ast::Pat) {
+impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
+    fn visit_pat(&mut self, p: &'a ast::Pat) {
         match p.node {
             PatKind::Struct(ref path, ..) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::TupleStruct(ref path, ..) |
             PatKind::Path(_, ref path) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::Ident(bm, ref path1, _) => {
                 debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
@@ -854,9 +893,7 @@ impl<'a> Visitor<'a> for PathCollector {
                     ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
                     ast::BindingMode::ByValue(mt) => mt,
                 };
-                // collect path for either visit_local or visit_arm
-                let path = ast::Path::from_ident(path1.span, path1.node);
-                self.collected_paths.push((p.id, path, immut));
+                self.collected_idents.push((p.id, path1.node, path1.span, immut));
             }
             _ => {}
         }
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index b0844d1b824..80c1b0ebeb0 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -477,8 +477,13 @@ impl Sig for ast::Item {
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
-            ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => {
+            ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
                 let mut text = String::new();
+
+                if is_auto == ast::IsAuto::Yes {
+                    text.push_str("auto ");
+                }
+
                 if unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
@@ -499,7 +504,7 @@ impl Sig for ast::Item {
 
                 Ok(sig)
             }
-            ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 let mut text = String::new();
                 if unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index b9d82b8e251..5bfb4d1b3b2 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -103,47 +103,6 @@ impl<'a> SpanUtils<'a> {
         }
     }
 
-    // Return the span for the last ident before a `(` or `<` or '::<' and outside any
-    // any brackets, or the last span.
-    pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut prev = toks.real_token();
-        let mut result = None;
-        let mut bracket_count = 0;
-        let mut prev_span = None;
-        while prev.tok != token::Eof {
-            prev_span = None;
-            let mut next = toks.real_token();
-
-            if (next.tok == token::OpenDelim(token::Paren) || next.tok == token::Lt) &&
-               bracket_count == 0 && prev.tok.is_ident() {
-                result = Some(prev.sp);
-            }
-
-            if bracket_count == 0 && next.tok == token::ModSep {
-                let old = prev;
-                prev = next;
-                next = toks.real_token();
-                if next.tok == token::Lt && old.tok.is_ident() {
-                    result = Some(old.sp);
-                }
-            }
-
-            bracket_count += match prev.tok {
-                token::OpenDelim(token::Paren) | token::Lt => 1,
-                token::CloseDelim(token::Paren) | token::Gt => -1,
-                token::BinOp(token::Shr) => -2,
-                _ => 0,
-            };
-
-            if prev.tok.is_ident() && bracket_count == 0 {
-                prev_span = Some(prev.sp);
-            }
-            prev = next;
-        }
-        result.or(prev_span)
-    }
-
     // Return the span for the last ident before a `<` and outside any
     // angle brackets, or the last span.
     pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
@@ -330,7 +289,7 @@ impl<'a> SpanUtils<'a> {
 }
 
 macro_rules! filter {
-    ($util: expr, $span: ident, $parent: expr, None) => {
+    ($util: expr, $span: expr, $parent: expr, None) => {
         if $util.filter_generated($span, $parent) {
             return None;
         }
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 5b7879ea58e..f797464c1f8 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -19,6 +19,7 @@ owning_ref = "0.3.3"
 rustc-demangle = "0.1.4"
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
+rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index b203bd640cf..907693ea8a3 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -1222,7 +1222,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
                 let canonical = f.replace("-", "_");
                 let canonical_name = name.replace("-", "_");
 
-                // Look for `.rust-cgu.o` at the end of the filename to conclude
+                // Look for `.rcgu.o` at the end of the filename to conclude
                 // that this is a Rust-related object file.
                 fn looks_like_rust(s: &str) -> bool {
                     let path = Path::new(s);
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index eb1c5cb7881..23890905718 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -21,6 +21,7 @@ use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::util::nodemap::FxHashMap;
 use rustc_allocator::ALLOCATOR_METHODS;
+use syntax::attr;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
@@ -124,6 +125,12 @@ pub fn provide_local(providers: &mut Providers) {
                               None,
                               SymbolExportLevel::Rust));
         }
+
+        // Sort so we get a stable incr. comp. hash.
+        local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
+            name1.cmp(name2)
+        });
+
         Arc::new(local_crate)
     };
 }
@@ -147,7 +154,7 @@ pub fn provide_extern(providers: &mut Providers) {
         let special_runtime_crate =
             tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
 
-        let crate_exports = tcx
+        let mut crate_exports: Vec<_> = tcx
             .exported_symbol_ids(cnum)
             .iter()
             .map(|&def_id| {
@@ -175,12 +182,25 @@ pub fn provide_extern(providers: &mut Providers) {
             })
             .collect();
 
+        // Sort so we get a stable incr. comp. hash.
+        crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
+            name1.cmp(name2)
+        });
+
         Arc::new(crate_exports)
     };
 }
 
 fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
-    if tcx.contains_extern_indicator(sym_def_id) {
+    // We export anything that's not mangled at the "C" layer as it probably has
+    // to do with ABI concerns. We do not, however, apply such treatment to
+    // special symbols in the standard library for various plumbing between
+    // core/std/allocators/etc. For example symbols used to hook up allocation
+    // are not considered for export
+    let is_extern = tcx.contains_extern_indicator(sym_def_id);
+    let std_internal = attr::contains_name(&tcx.get_attrs(sym_def_id),
+                                           "rustc_std_internal_symbol");
+    if is_extern && !std_internal {
         SymbolExportLevel::C
     } else {
         SymbolExportLevel::Rust
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 5550ab9fa55..d59d8ca1a78 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -32,7 +32,7 @@ use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc::ty::TyCtxt;
 use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry};
 use rustc::util::fs::{link_or_copy, rename_or_copy_remove};
-use errors::{self, Handler, Level, DiagnosticBuilder, FatalError};
+use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
 use errors::emitter::{Emitter};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
@@ -76,6 +76,13 @@ pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
     ("large", llvm::CodeModel::Large),
 ];
 
+pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
+    ("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
+    ("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
+    ("initial-exec", llvm::ThreadLocalMode::InitialExec),
+    ("local-exec", llvm::ThreadLocalMode::LocalExec),
+];
+
 pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
     match llvm::last_error() {
         Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
@@ -173,9 +180,7 @@ pub fn target_machine_factory(sess: &Session)
         Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid code model",
-                             sess.opts
-                                 .cg
-                                 .code_model));
+                              code_model_arg));
             sess.abort_if_errors();
             bug!();
         }
@@ -1262,7 +1267,7 @@ enum Message {
 
 struct Diagnostic {
     msg: String,
-    code: Option<String>,
+    code: Option<DiagnosticId>,
     lvl: Level,
 }
 
@@ -2015,7 +2020,7 @@ impl SharedEmitterMain {
                         Some(ref code) => {
                             handler.emit_with_code(&MultiSpan::new(),
                                                    &diag.msg,
-                                                   &code,
+                                                   code.clone(),
                                                    diag.lvl);
                         }
                         None => {
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index eaf7392aab5..4ae289cfada 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -196,7 +196,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
 
         for attr in attrs {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local(g, true);
+                llvm::set_thread_local_mode(g, ccx.tls_model());
             }
         }
 
@@ -215,7 +215,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
         // symbol and another one doesn't.
         for attr in ccx.tcx().get_attrs(def_id).iter() {
             if attr.check_name("thread_local") {
-                llvm::set_thread_local(g, true);
+                llvm::set_thread_local_mode(g, ccx.tls_model());
             }
         }
         if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
@@ -305,9 +305,8 @@ pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         debuginfo::create_global_var_metadata(ccx, id, g);
 
-        if attr::contains_name(attrs,
-                               "thread_local") {
-            llvm::set_thread_local(g, true);
+        if attr::contains_name(attrs, "thread_local") {
+            llvm::set_thread_local_mode(g, ccx.tls_model());
         }
 
         base::set_link_section(ccx, g, attrs);
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 9df057c77a9..cb71ef104d3 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -52,6 +52,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     check_overflow: bool,
     use_dll_storage_attrs: bool,
+    tls_model: llvm::ThreadLocalMode,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -159,9 +160,25 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
         Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid relocation mode",
-                             sess.opts
-                                 .cg
-                                 .code_model));
+                              reloc_model_arg));
+            sess.abort_if_errors();
+            bug!();
+        }
+    }
+}
+
+fn get_tls_model(sess: &Session) -> llvm::ThreadLocalMode {
+    let tls_model_arg = match sess.opts.debugging_opts.tls_model {
+        Some(ref s) => &s[..],
+        None => &sess.target.target.options.tls_model[..],
+    };
+
+    match ::back::write::TLS_MODEL_ARGS.iter().find(
+        |&&arg| arg.0 == tls_model_arg) {
+        Some(x) => x.1,
+        _ => {
+            sess.err(&format!("{:?} is not a valid TLS model",
+                              tls_model_arg));
             sess.abort_if_errors();
             bug!();
         }
@@ -283,10 +300,13 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
 
         let check_overflow = tcx.sess.overflow_checks();
 
+        let tls_model = get_tls_model(&tcx.sess);
+
         SharedCrateContext {
             tcx,
             check_overflow,
             use_dll_storage_attrs,
+            tls_model,
         }
     }
 
@@ -528,6 +548,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         self.shared.use_dll_storage_attrs()
     }
 
+    pub fn tls_model(&self) -> llvm::ThreadLocalMode {
+        self.shared.tls_model
+    }
+
     /// Generate a new symbol name with the given prefix. This symbol name must
     /// only be used for definitions with `internal` or `private` linkage.
     pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index c0460fb4852..29394af3396 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -24,6 +24,7 @@
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
+#![feature(i128)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
@@ -43,6 +44,7 @@ extern crate libc;
 extern crate owning_ref;
 #[macro_use] extern crate rustc;
 extern crate rustc_allocator;
+extern crate rustc_apfloat;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate rustc_incremental;
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index 00815be278e..73f60ff29a8 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -228,7 +228,8 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Unreachable |
                 TerminatorKind::SwitchInt { .. } |
-                TerminatorKind::Yield { .. }  => {
+                TerminatorKind::Yield { .. } |
+                TerminatorKind::FalseEdges { .. } => {
                     /* nothing to do */
                 }
                 TerminatorKind::Call { cleanup: unwind, .. } |
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 591aa974666..11d992bd4cf 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -583,7 +583,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         cleanup);
             }
             mir::TerminatorKind::GeneratorDrop |
-            mir::TerminatorKind::Yield { .. } => bug!("generator ops in trans"),
+            mir::TerminatorKind::Yield { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => bug!("generator ops in trans"),
         }
     }
 
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index cea7b9585d8..6573e507bd3 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -11,7 +11,7 @@
 use llvm::{self, ValueRef};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
 use rustc_const_math::ConstInt::*;
-use rustc_const_math::{ConstInt, ConstMathErr};
+use rustc_const_math::{ConstInt, ConstMathErr, MAX_F32_PLUS_HALF_ULP};
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
 use rustc::traits;
@@ -21,6 +21,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::layout::{self, LayoutTyper};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::subst::{Kind, Substs, Subst};
+use rustc_apfloat::{ieee, Float, Status};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use {adt, base, machine};
 use abi::{self, Abi};
@@ -689,20 +690,18 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                                     llvm::LLVMConstIntCast(llval, ll_t_out.to_ref(), s)
                                 }
                                 (CastTy::Int(_), CastTy::Float) => {
-                                    if signed {
-                                        llvm::LLVMConstSIToFP(llval, ll_t_out.to_ref())
-                                    } else {
-                                        llvm::LLVMConstUIToFP(llval, ll_t_out.to_ref())
-                                    }
+                                    cast_const_int_to_float(self.ccx, llval, signed, ll_t_out)
                                 }
                                 (CastTy::Float, CastTy::Float) => {
                                     llvm::LLVMConstFPCast(llval, ll_t_out.to_ref())
                                 }
                                 (CastTy::Float, CastTy::Int(IntTy::I)) => {
-                                    llvm::LLVMConstFPToSI(llval, ll_t_out.to_ref())
+                                    cast_const_float_to_int(self.ccx, &operand,
+                                                            true, ll_t_out, span)
                                 }
                                 (CastTy::Float, CastTy::Int(_)) => {
-                                    llvm::LLVMConstFPToUI(llval, ll_t_out.to_ref())
+                                    cast_const_float_to_int(self.ccx, &operand,
+                                                            false, ll_t_out, span)
                                 }
                                 (CastTy::Ptr(_), CastTy::Ptr(_)) |
                                 (CastTy::FnPtr, CastTy::Ptr(_)) |
@@ -955,6 +954,64 @@ pub fn const_scalar_checked_binop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+unsafe fn cast_const_float_to_int(ccx: &CrateContext,
+                                  operand: &Const,
+                                  signed: bool,
+                                  int_ty: Type,
+                                  span: Span) -> ValueRef {
+    let llval = operand.llval;
+    let float_bits = match operand.ty.sty {
+        ty::TyFloat(fty) => fty.bit_width(),
+        _ => bug!("cast_const_float_to_int: operand not a float"),
+    };
+    // Note: this breaks if llval is a complex constant expression rather than a simple constant.
+    // One way that might happen would be if addresses could be turned into integers in constant
+    // expressions, but that doesn't appear to be possible?
+    // In any case, an ICE is better than producing undef.
+    let llval_bits = consts::bitcast(llval, Type::ix(ccx, float_bits as u64));
+    let bits = const_to_opt_u128(llval_bits, false).unwrap_or_else(|| {
+        panic!("could not get bits of constant float {:?}",
+               Value(llval));
+    });
+    let int_width = int_ty.int_width() as usize;
+    // Try to convert, but report an error for overflow and NaN. This matches HIR const eval.
+    let cast_result = match float_bits {
+        32 if signed => ieee::Single::from_bits(bits).to_i128(int_width).map(|v| v as u128),
+        64 if signed => ieee::Double::from_bits(bits).to_i128(int_width).map(|v| v as u128),
+        32 => ieee::Single::from_bits(bits).to_u128(int_width),
+        64 => ieee::Double::from_bits(bits).to_u128(int_width),
+        n => bug!("unsupported float width {}", n),
+    };
+    if cast_result.status.contains(Status::INVALID_OP) {
+        let err = ConstEvalErr { span: span, kind: ErrKind::CannotCast };
+        err.report(ccx.tcx(), span, "expression");
+    }
+    C_big_integral(int_ty, cast_result.value)
+}
+
+unsafe fn cast_const_int_to_float(ccx: &CrateContext,
+                                  llval: ValueRef,
+                                  signed: bool,
+                                  float_ty: Type) -> ValueRef {
+    // Note: this breaks if llval is a complex constant expression rather than a simple constant.
+    // One way that might happen would be if addresses could be turned into integers in constant
+    // expressions, but that doesn't appear to be possible?
+    // In any case, an ICE is better than producing undef.
+    let value = const_to_opt_u128(llval, signed).unwrap_or_else(|| {
+        panic!("could not get z128 value of constant integer {:?}",
+               Value(llval));
+    });
+    if signed {
+        llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
+    } else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
+        // We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
+        let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
+        consts::bitcast(infinity_bits, float_ty)
+    } else {
+        llvm::LLVMConstUIToFP(llval, float_ty.to_ref())
+    }
+}
+
 impl<'a, 'tcx> MirContext<'a, 'tcx> {
     pub fn trans_constant(&mut self,
                           bcx: &Builder<'a, 'tcx>,
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 777b86387e8..19131a68d86 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -15,11 +15,15 @@ use rustc::ty::layout::{Layout, LayoutTyper};
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir;
 use rustc::middle::lang_items::ExchangeMallocFnLangItem;
+use rustc_apfloat::{ieee, Float, Status, Round};
+use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
+use std::{u128, i128};
 
 use base;
 use builder::Builder;
 use callee;
-use common::{self, val_ty, C_bool, C_i32, C_null, C_usize, C_uint};
+use common::{self, val_ty, C_bool, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_big_integral};
+use consts;
 use adt;
 use machine;
 use monomorphize;
@@ -333,14 +337,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                 bcx.ptrtoint(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Ptr(_)) =>
                                 bcx.inttoptr(llval, ll_t_out),
-                            (CastTy::Int(_), CastTy::Float) if signed =>
-                                bcx.sitofp(llval, ll_t_out),
                             (CastTy::Int(_), CastTy::Float) =>
-                                bcx.uitofp(llval, ll_t_out),
+                                cast_int_to_float(&bcx, signed, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(IntTy::I)) =>
-                                bcx.fptosi(llval, ll_t_out),
+                                cast_float_to_int(&bcx, true, llval, ll_t_in, ll_t_out),
                             (CastTy::Float, CastTy::Int(_)) =>
-                                bcx.fptoui(llval, ll_t_out),
+                                cast_float_to_int(&bcx, false, llval, ll_t_in, ll_t_out),
                             _ => bug!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
                         };
                         OperandValue::Immediate(newval)
@@ -815,3 +817,158 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
 
     bcx.ccx.get_intrinsic(&name)
 }
+
+fn cast_int_to_float(bcx: &Builder,
+                     signed: bool,
+                     x: ValueRef,
+                     int_ty: Type,
+                     float_ty: Type) -> ValueRef {
+    // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
+    // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
+    // LLVM's uitofp produces undef in those cases, so we manually check for that case.
+    let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
+    if is_u128_to_f32 && bcx.sess().opts.debugging_opts.saturating_float_casts {
+        // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
+        // and for everything else LLVM's uitofp works just fine.
+        let max = C_big_integral(int_ty, MAX_F32_PLUS_HALF_ULP);
+        let overflow = bcx.icmp(llvm::IntUGE, x, max);
+        let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
+        let infinity = consts::bitcast(infinity_bits, float_ty);
+        bcx.select(overflow, infinity, bcx.uitofp(x, float_ty))
+    } else {
+        if signed {
+            bcx.sitofp(x, float_ty)
+        } else {
+            bcx.uitofp(x, float_ty)
+        }
+    }
+}
+
+fn cast_float_to_int(bcx: &Builder,
+                     signed: bool,
+                     x: ValueRef,
+                     float_ty: Type,
+                     int_ty: Type) -> ValueRef {
+    let fptosui_result = if signed {
+        bcx.fptosi(x, int_ty)
+    } else {
+        bcx.fptoui(x, int_ty)
+    };
+
+    if !bcx.sess().opts.debugging_opts.saturating_float_casts {
+        return fptosui_result;
+    }
+    // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
+    // destination integer type after rounding towards zero. This `undef` value can cause UB in
+    // safe code (see issue #10184), so we implement a saturating conversion on top of it:
+    // Semantically, the mathematical value of the input is rounded towards zero to the next
+    // mathematical integer, and then the result is clamped into the range of the destination
+    // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
+    // the destination integer type. NaN is mapped to 0.
+    //
+    // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
+    // a value representable in int_ty.
+    // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
+    // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
+    // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
+    // representable. Note that this only works if float_ty's exponent range is sufficently large.
+    // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
+    // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
+    // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
+    // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
+    // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
+    fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
+        let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
+        assert_eq!(rounded_min.status, Status::OK);
+        let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
+        assert!(rounded_max.value.is_finite());
+        (rounded_min.value.to_bits(), rounded_max.value.to_bits())
+    }
+    fn int_max(signed: bool, int_ty: Type) -> u128 {
+        let shift_amount = 128 - int_ty.int_width();
+        if signed {
+            i128::MAX as u128 >> shift_amount
+        } else {
+            u128::MAX >> shift_amount
+        }
+    }
+    fn int_min(signed: bool, int_ty: Type) -> i128 {
+        if signed {
+            i128::MIN >> (128 - int_ty.int_width())
+        } else {
+            0
+        }
+    }
+    let float_bits_to_llval = |bits| {
+        let bits_llval = match float_ty.float_width() {
+            32 => C_u32(bcx.ccx, bits as u32),
+            64 => C_u64(bcx.ccx, bits as u64),
+            n => bug!("unsupported float width {}", n),
+        };
+        consts::bitcast(bits_llval, float_ty)
+    };
+    let (f_min, f_max) = match float_ty.float_width() {
+        32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty),
+        64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty),
+        n => bug!("unsupported float width {}", n),
+    };
+    let f_min = float_bits_to_llval(f_min);
+    let f_max = float_bits_to_llval(f_max);
+    // To implement saturation, we perform the following steps:
+    //
+    // 1. Cast x to an integer with fpto[su]i. This may result in undef.
+    // 2. Compare x to f_min and f_max, and use the comparison results to select:
+    //  a) int_ty::MIN if x < f_min or x is NaN
+    //  b) int_ty::MAX if x > f_max
+    //  c) the result of fpto[su]i otherwise
+    // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
+    //
+    // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
+    // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
+    // undef does not introduce any non-determinism either.
+    // More importantly, the above procedure correctly implements saturating conversion.
+    // Proof (sketch):
+    // If x is NaN, 0 is returned by definition.
+    // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
+    // This yields three cases to consider:
+    // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
+    //     saturating conversion for inputs in that range.
+    // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
+    //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
+    //     than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
+    //     is correct.
+    // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
+    //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
+    // QED.
+
+    // Step 1 was already performed above.
+
+    // Step 2: We use two comparisons and two selects, with %s1 being the result:
+    //     %less_or_nan = fcmp ult %x, %f_min
+    //     %greater = fcmp olt %x, %f_max
+    //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
+    //     %s1 = select %greater, int_ty::MAX, %s0
+    // Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the
+    // operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1
+    // becomes int_ty::MIN if x is NaN.
+    // Performance note: Unordered comparison can be lowered to a "flipped" comparison and a
+    // negation, and the negation can be merged into the select. Therefore, it not necessarily any
+    // more expensive than a ordered ("normal") comparison. Whether these optimizations will be
+    // performed is ultimately up to the backend, but at least x86 does perform them.
+    let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
+    let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
+    let int_max = C_big_integral(int_ty, int_max(signed, int_ty));
+    let int_min = C_big_integral(int_ty, int_min(signed, int_ty) as u128);
+    let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
+    let s1 = bcx.select(greater, int_max, s0);
+
+    // Step 3: NaN replacement.
+    // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
+    // Therefore we only need to execute this step for signed integer types.
+    if signed {
+        // LLVM has no isNaN predicate, so we use (x == x) instead
+        bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
+    } else {
+        s1
+    }
+}
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 6980ba8a525..03c0f13e2f5 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -104,7 +104,7 @@
 
 use collector::InliningMap;
 use common;
-use rustc::dep_graph::{DepNode, WorkProductId};
+use rustc::dep_graph::WorkProductId;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::middle::trans::{Linkage, Visibility};
@@ -147,10 +147,6 @@ pub trait CodegenUnitExt<'tcx> {
         WorkProductId::from_cgu_name(self.name())
     }
 
-    fn work_product_dep_node(&self) -> DepNode {
-        self.work_product_id().to_dep_node()
-    }
-
     fn items_in_deterministic_order<'a>(&self,
                                         tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                         -> Vec<(TransItem<'tcx>,
@@ -253,14 +249,6 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         cgu1.name().cmp(cgu2.name())
     });
 
-    if tcx.sess.opts.enable_dep_node_debug_strs() {
-        for cgu in &result {
-            let dep_node = cgu.work_product_dep_node();
-            tcx.dep_graph.register_dep_node_debug_str(dep_node,
-                                                            || cgu.name().to_string());
-        }
-    }
-
     result
 }
 
diff --git a/src/librustc_trans_utils/collector.rs b/src/librustc_trans_utils/collector.rs
index cf9b80e5ed4..429471221c6 100644
--- a/src/librustc_trans_utils/collector.rs
+++ b/src/librustc_trans_utils/collector.rs
@@ -211,6 +211,8 @@ use trans_item::{TransItemExt, DefPathBasedNames, InstantiationMode};
 
 use rustc_data_structures::bitvec::BitVector;
 
+use syntax::attr;
+
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
     Eager,
@@ -324,9 +326,14 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut roots = Vec::new();
 
     {
+        let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _)| {
+            tcx.hir.local_def_id(node_id)
+        });
+
         let mut visitor = RootCollector {
             tcx,
             mode,
+            entry_fn,
             output: &mut roots,
         };
 
@@ -623,7 +630,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             mir::TerminatorKind::Unreachable |
             mir::TerminatorKind::Assert { .. } => {}
             mir::TerminatorKind::GeneratorDrop |
-            mir::TerminatorKind::Yield { .. } => bug!(),
+            mir::TerminatorKind::Yield { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => bug!(),
         }
 
         self.super_terminator_kind(block, kind, location);
@@ -874,6 +882,7 @@ struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mode: TransItemCollectionMode,
     output: &'b mut Vec<TransItem<'tcx>>,
+    entry_fn: Option<DefId>,
 }
 
 impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
@@ -883,7 +892,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
             hir::ItemUse(..)         |
             hir::ItemForeignMod(..)  |
             hir::ItemTy(..)          |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTrait(..)       |
             hir::ItemMod(..)         => {
                 // Nothing to do, just keep recursing...
@@ -931,10 +940,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
                 let tcx = self.tcx;
                 let def_id = tcx.hir.local_def_id(item.id);
 
-                if (self.mode == TransItemCollectionMode::Eager ||
-                    !tcx.is_const_fn(def_id) || tcx.is_exported_symbol(def_id)) &&
-                   !item_has_type_parameters(tcx, def_id) {
-
+                if self.is_root(def_id) {
                     debug!("RootCollector: ItemFn({})",
                            def_id_to_string(tcx, def_id));
 
@@ -956,10 +962,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
                 let tcx = self.tcx;
                 let def_id = tcx.hir.local_def_id(ii.id);
 
-                if (self.mode == TransItemCollectionMode::Eager ||
-                    !tcx.is_const_fn(def_id) ||
-                    tcx.is_exported_symbol(def_id)) &&
-                   !item_has_type_parameters(tcx, def_id) {
+                if self.is_root(def_id) {
                     debug!("RootCollector: MethodImplItem({})",
                            def_id_to_string(tcx, def_id));
 
@@ -972,6 +975,22 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
     }
 }
 
+impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
+    fn is_root(&self, def_id: DefId) -> bool {
+        !item_has_type_parameters(self.tcx, def_id) && match self.mode {
+            TransItemCollectionMode::Eager => {
+                true
+            }
+            TransItemCollectionMode::Lazy => {
+                self.entry_fn == Some(def_id) ||
+                self.tcx.is_exported_symbol(def_id) ||
+                attr::contains_name(&self.tcx.get_attrs(def_id),
+                                    "rustc_std_internal_symbol")
+            }
+        }
+    }
+}
+
 fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
     let generics = tcx.generics_of(def_id);
     generics.parent_types as usize + generics.types.len() > 0
diff --git a/src/librustc_trans_utils/common.rs b/src/librustc_trans_utils/common.rs
index ec9c5b1119b..47968afd70d 100644
--- a/src/librustc_trans_utils/common.rs
+++ b/src/librustc_trans_utils/common.rs
@@ -51,7 +51,8 @@ pub fn requests_inline<'a, 'tcx>(
         // available to normal end-users.
         return true
     }
-    attr::requests_inline(&instance.def.attrs(tcx)[..])
+    attr::requests_inline(&instance.def.attrs(tcx)[..]) ||
+        tcx.is_const_fn(instance.def.def_id())
 }
 
 pub fn is_inline_instance<'a, 'tcx>(
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 6a341a1e7d3..d6f8707b874 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -40,14 +40,12 @@ extern crate rustc_data_structures;
 extern crate syntax;
 extern crate syntax_pos;
 
-use rustc::ty::TyCtxt;
+use rustc::ty::{TyCtxt, Instance};
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map as hir_map;
 use rustc::util::nodemap::NodeSet;
 
-use syntax::attr;
-
 pub mod common;
 pub mod link;
 pub mod collector;
@@ -77,7 +75,7 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
 ///
 /// This list is later used by linkers to determine the set of symbols needed to
 /// be exposed from a dynamic library and it's also encoded into the metadata.
-pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
+pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
     tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
         // Next, we want to ignore some FFI functions that are not exposed from
         // this crate. Reachable FFI functions can be lumped into two
@@ -107,11 +105,10 @@ pub fn find_exported_symbols(tcx: TyCtxt) -> NodeSet {
                 node: hir::ImplItemKind::Method(..), .. }) => {
                 let def_id = tcx.hir.local_def_id(id);
                 let generics = tcx.generics_of(def_id);
-                let attributes = tcx.get_attrs(def_id);
                 (generics.parent_types == 0 && generics.types.is_empty()) &&
                 // Functions marked with #[inline] are only ever translated
                 // with "internal" linkage and are never exported.
-                !attr::requests_inline(&attributes)
+                !common::requests_inline(tcx, &Instance::mono(tcx, def_id))
             }
 
             _ => false
diff --git a/src/librustc_typeck/README.md b/src/librustc_typeck/README.md
index a38f04e304b..1abc914e7d6 100644
--- a/src/librustc_typeck/README.md
+++ b/src/librustc_typeck/README.md
@@ -12,7 +12,7 @@ The `rustc_typeck` crate contains the source for "type collection" and
 
 ## Type collection
 
-Type "collection" is the process of convering the types found in the
+Type "collection" is the process of converting the types found in the
 HIR (`hir::Ty`), which represent the syntactic things that the user
 wrote, into the **internal representation** used by the compiler
 (`Ty<'tcx>`) -- we also do similar conversions for where-clauses and
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index c7f7e62fd61..1471e235156 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1206,60 +1206,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         bare_fn_ty
     }
 
-    pub fn ty_of_closure(&self,
-        unsafety: hir::Unsafety,
-        decl: &hir::FnDecl,
-        abi: abi::Abi,
-        expected_sig: Option<ty::FnSig<'tcx>>)
-        -> ty::PolyFnSig<'tcx>
-    {
-        debug!("ty_of_closure(expected_sig={:?})",
-               expected_sig);
-
-        let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| {
-            let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
-                // no guarantee that the correct number of expected args
-                // were supplied
-                if i < e.inputs().len() {
-                    Some(e.inputs()[i])
-                } else {
-                    None
-                }
-            });
-            self.ty_of_arg(a, expected_arg_ty)
-        });
-
-        let expected_ret_ty = expected_sig.as_ref().map(|e| e.output());
-
-        let output_ty = match decl.output {
-            hir::Return(ref output) => {
-                if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) {
-                    self.record_ty(output.hir_id, expected_ret_ty, output.span);
-                    expected_ret_ty
-                } else {
-                    self.ast_ty_to_ty(&output)
-                }
-            }
-            hir::DefaultReturn(span) => {
-                if let Some(expected_ret_ty) = expected_ret_ty {
-                    expected_ret_ty
-                } else {
-                    self.ty_infer(span)
-                }
-            }
-        };
-
-        debug!("ty_of_closure: output_ty={:?}", output_ty);
-
-        ty::Binder(self.tcx().mk_fn_sig(
-            input_tys,
-            output_ty,
-            decl.variadic,
-            unsafety,
-            abi
-        ))
-    }
-
     /// Given the bounds on an object, determines what single region bound (if any) we can
     /// use to summarize this type. The basic idea is that we will use the bound the user
     /// provided, if they provided one, and otherwise search the supertypes of trait bounds
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index ab8994bcae2..272f13b2803 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -23,6 +23,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::cmp;
 use syntax::ast;
 use syntax::codemap::Spanned;
+use syntax::feature_gate;
 use syntax::ptr::P;
 use syntax_pos::Span;
 
@@ -68,7 +69,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             PatKind::Binding(..) |
             PatKind::Ref(..) => false,
         };
-        if is_non_ref_pat && tcx.sess.features.borrow().match_default_bindings {
+        if is_non_ref_pat {
             debug!("pattern is non reference pattern");
             let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
 
@@ -113,10 +114,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
             };
             if pat_adjustments.len() > 0 {
-                debug!("default binding mode is now {:?}", def_bm);
-                self.inh.tables.borrow_mut()
-                    .pat_adjustments_mut()
-                    .insert(pat.hir_id, pat_adjustments);
+                if tcx.sess.features.borrow().match_default_bindings {
+                    debug!("default binding mode is now {:?}", def_bm);
+                    self.inh.tables.borrow_mut()
+                        .pat_adjustments_mut()
+                        .insert(pat.hir_id, pat_adjustments);
+                } else {
+                    let mut err = feature_gate::feature_err(
+                        &tcx.sess.parse_sess,
+                        "match_default_bindings",
+                        pat.span,
+                        feature_gate::GateIssue::Language,
+                        "non-reference pattern used to match a reference",
+                    );
+                    if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(pat.span) {
+                        err.span_suggestion(pat.span, "consider using", format!("&{}", &snippet));
+                    }
+                    err.emit();
+                }
             }
         }
 
@@ -325,8 +340,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             if let Some(mut err) = err {
                                 if is_arg {
                                     if let PatKind::Binding(..) = inner.node {
-                                        if let Ok(snippet) = self.sess().codemap()
-                                                                        .span_to_snippet(pat.span)
+                                        if let Ok(snippet) = tcx.sess.codemap()
+                                                                     .span_to_snippet(pat.span)
                                         {
                                             err.help(&format!("did you mean `{}: &{}`?",
                                                               &snippet[1..],
@@ -810,10 +825,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                def_bm: ty::BindingMode) {
         let tcx = self.tcx;
 
-        let (substs, kind_name) = match adt_ty.sty {
-            ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
+        let (substs, adt) = match adt_ty.sty {
+            ty::TyAdt(adt, substs) => (substs, adt),
             _ => span_bug!(span, "struct pattern is not an ADT")
         };
+        let kind_name = adt.variant_descr();
 
         // Index the struct fields' types.
         let field_map = variant.fields
@@ -867,6 +883,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             self.check_pat_walk(&field.pat, field_ty, def_bm, true);
         }
 
+        // Require `..` if struct has non_exhaustive attribute.
+        if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc {
+            span_err!(tcx.sess, span, E0638,
+                      "`..` required with {} marked as non-exhaustive",
+                      kind_name);
+        }
+
         // Report an error if incorrect number of the fields were specified.
         if kind_name == "union" {
             if fields.len() != 1 {
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 7b35b466830..d68c139894b 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -83,28 +83,30 @@ enum PointerKind<'tcx> {
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     /// Returns the kind of unsize information of t, or None
-    /// if t is sized or it is unknown.
-    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> PointerKind<'tcx> {
+    /// if t is unknown.
+    fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> Option<PointerKind<'tcx>> {
         if self.type_is_known_to_be_sized(t, span) {
-            return PointerKind::Thin;
+            return Some(PointerKind::Thin);
         }
 
         match t.sty {
-            ty::TySlice(_) | ty::TyStr => PointerKind::Length,
+            ty::TySlice(_) | ty::TyStr => Some(PointerKind::Length),
             ty::TyDynamic(ref tty, ..) =>
-                PointerKind::Vtable(tty.principal().map(|p| p.def_id())),
+                Some(PointerKind::Vtable(tty.principal().map(|p| p.def_id()))),
             ty::TyAdt(def, substs) if def.is_struct() => {
                 // FIXME(arielb1): do some kind of normalization
                 match def.struct_variant().fields.last() {
-                    None => PointerKind::Thin,
+                    None => Some(PointerKind::Thin),
                     Some(f) => self.pointer_kind(f.ty(self.tcx, substs), span),
                 }
             }
             // Pointers to foreign types are thin, despite being unsized
-            ty::TyForeign(..) => PointerKind::Thin,
+            ty::TyForeign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
-            ty::TyProjection(ref pi) => PointerKind::OfProjection(pi),
-            ty::TyParam(ref p) => PointerKind::OfParam(p),
+            ty::TyProjection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::TyParam(ref p) => Some(PointerKind::OfParam(p)),
+            // Insufficient type information.
+            ty::TyInfer(_) => None,
             _ => panic!(),
         }
     }
@@ -123,6 +125,8 @@ enum CastError {
     NeedViaThinPtr,
     NeedViaInt,
     NonScalar,
+    UnknownExprPtrKind,
+    UnknownCastPtrKind,
 }
 
 fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
@@ -241,6 +245,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                                  self.expr_ty,
                                  fcx.ty_to_string(self.cast_ty)).emit();
             }
+            CastError::UnknownCastPtrKind |
+            CastError::UnknownExprPtrKind => {
+                let unknown_cast_to = match e {
+                    CastError::UnknownCastPtrKind => true,
+                    CastError::UnknownExprPtrKind => false,
+                    _ => bug!(),
+                };
+                let mut err = struct_span_err!(fcx.tcx.sess, self.span, E0641,
+                                               "cannot cast {} a pointer of an unknown kind",
+                                               if unknown_cast_to { "to" } else { "from" });
+                err.note("The type information given here is insufficient to check whether \
+                          the pointer cast is valid");
+                if unknown_cast_to {
+                    err.span_suggestion_short(self.cast_span,
+                                              "consider giving more type information",
+                                              String::new());
+                }
+                err.emit();
+            }
         }
     }
 
@@ -457,14 +480,27 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
         debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
         // ptr-ptr cast. vtables must match.
 
-        // Cast to thin pointer is OK
+        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
         let cast_kind = fcx.pointer_kind(m_cast.ty, self.span);
+
+        let cast_kind = match cast_kind {
+            // We can't cast if target pointer kind is unknown
+            None => return Err(CastError::UnknownCastPtrKind),
+            Some(cast_kind) => cast_kind,
+        };
+
+        // Cast to thin pointer is OK
         if cast_kind == PointerKind::Thin {
             return Ok(CastKind::PtrPtrCast);
         }
 
+        let expr_kind = match expr_kind {
+            // We can't cast to fat pointer if source pointer kind is unknown
+            None => return Err(CastError::UnknownExprPtrKind),
+            Some(expr_kind) => expr_kind,
+        };
+
         // thin -> fat? report invalid cast (don't complain about vtable kinds)
-        let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
         if expr_kind == PointerKind::Thin {
             return Err(CastError::SizedUnsizedCast);
         }
@@ -483,10 +519,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                            -> Result<CastKind, CastError> {
         // fptr-ptr cast. must be to thin ptr
 
-        if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::FnPtrPtrCast)
-        } else {
-            Err(CastError::IllegalCast)
+        match fcx.pointer_kind(m_cast.ty, self.span) {
+            None => Err(CastError::UnknownCastPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::FnPtrPtrCast),
+            _ => Err(CastError::IllegalCast),
         }
     }
 
@@ -496,10 +532,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. must be from thin ptr
 
-        if fcx.pointer_kind(m_expr.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::PtrAddrCast)
-        } else {
-            Err(CastError::NeedViaThinPtr)
+        match fcx.pointer_kind(m_expr.ty, self.span) {
+            None => Err(CastError::UnknownExprPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::PtrAddrCast),
+            _ => Err(CastError::NeedViaThinPtr),
         }
     }
 
@@ -533,10 +569,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError> {
         // ptr-addr cast. pointer must be thin.
-        if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
-            Ok(CastKind::AddrPtrCast)
-        } else {
-            Err(CastError::IllegalCast)
+        match fcx.pointer_kind(m_cast.ty, self.span) {
+            None => Err(CastError::UnknownCastPtrKind),
+            Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
+            _ => Err(CastError::IllegalCast),
         }
     }
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 07159770d5b..d475fb0cf1a 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -13,25 +13,37 @@
 use super::{check_fn, Expectation, FnCtxt};
 
 use astconv::AstConv;
+use rustc::hir::def_id::DefId;
+use rustc::infer::{InferOk, InferResult};
+use rustc::infer::LateBoundRegionConversionTime;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::ty::{self, ToPolyTraitRef, Ty};
 use rustc::ty::subst::Substs;
+use rustc::ty::TypeFoldable;
 use std::cmp;
 use std::iter;
 use syntax::abi::Abi;
 use rustc::hir;
 
+struct ClosureSignatures<'tcx> {
+    bound_sig: ty::PolyFnSig<'tcx>,
+    liberated_sig: ty::FnSig<'tcx>,
+}
+
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn check_expr_closure(&self,
-                              expr: &hir::Expr,
-                              _capture: hir::CaptureClause,
-                              decl: &'gcx hir::FnDecl,
-                              body_id: hir::BodyId,
-                              expected: Expectation<'tcx>)
-                              -> Ty<'tcx> {
-        debug!("check_expr_closure(expr={:?},expected={:?})",
-               expr,
-               expected);
+    pub fn check_expr_closure(
+        &self,
+        expr: &hir::Expr,
+        _capture: hir::CaptureClause,
+        decl: &'gcx hir::FnDecl,
+        body_id: hir::BodyId,
+        expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        debug!(
+            "check_expr_closure(expr={:?},expected={:?})",
+            expr,
+            expected
+        );
 
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
@@ -44,70 +56,84 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
 
-    fn check_closure(&self,
-                     expr: &hir::Expr,
-                     opt_kind: Option<ty::ClosureKind>,
-                     decl: &'gcx hir::FnDecl,
-                     body: &'gcx hir::Body,
-                     expected_sig: Option<ty::FnSig<'tcx>>)
-                     -> Ty<'tcx> {
-        debug!("check_closure opt_kind={:?} expected_sig={:?}",
-               opt_kind,
-               expected_sig);
+    fn check_closure(
+        &self,
+        expr: &hir::Expr,
+        opt_kind: Option<ty::ClosureKind>,
+        decl: &'gcx hir::FnDecl,
+        body: &'gcx hir::Body,
+        expected_sig: Option<ty::FnSig<'tcx>>,
+    ) -> Ty<'tcx> {
+        debug!(
+            "check_closure(opt_kind={:?}, expected_sig={:?})",
+            opt_kind,
+            expected_sig
+        );
 
         let expr_def_id = self.tcx.hir.local_def_id(expr.id);
-        let sig = AstConv::ty_of_closure(self,
-                                         hir::Unsafety::Normal,
-                                         decl,
-                                         Abi::RustCall,
-                                         expected_sig);
-        // `deduce_expectations_from_expected_type` introduces late-bound
-        // lifetimes defined elsewhere, which we need to anonymize away.
-        let sig = self.tcx.anonymize_late_bound_regions(&sig);
+
+        let ClosureSignatures {
+            bound_sig,
+            liberated_sig,
+        } = self.sig_of_closure(expr_def_id, decl, body, expected_sig);
+
+        debug!("check_closure: ty_of_closure returns {:?}", liberated_sig);
+
+        let interior = check_fn(
+            self,
+            self.param_env,
+            liberated_sig,
+            decl,
+            expr.id,
+            body,
+            true,
+        ).1;
 
         // Create type variables (for now) to represent the transformed
         // types of upvars. These will be unified during the upvar
         // inference phase (`upvar.rs`).
-        let base_substs = Substs::identity_for_item(self.tcx,
-            self.tcx.closure_base_def_id(expr_def_id));
-        let substs = base_substs.extend_to(self.tcx, expr_def_id,
-                |_, _| span_bug!(expr.span, "closure has region param"),
-                |_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
+        let base_substs =
+            Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
+        let substs = base_substs.extend_to(
+            self.tcx,
+            expr_def_id,
+            |_, _| span_bug!(expr.span, "closure has region param"),
+            |_, _| {
+                self.infcx
+                    .next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
+            },
         );
-
-        let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
-        let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
-                                                            body.value.id,
-                                                            self.param_env,
-                                                            &fn_sig);
-
-        let interior = check_fn(self, self.param_env, fn_sig, decl, expr.id, body, true).1;
+        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
 
         if let Some(interior) = interior {
-            let closure_substs = ty::ClosureSubsts {
-                substs: substs,
-            };
+            let closure_substs = ty::ClosureSubsts { substs: substs };
             return self.tcx.mk_generator(expr_def_id, closure_substs, interior);
         }
 
-        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
-
-        debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
+        debug!(
+            "check_closure: expr.id={:?} closure_type={:?}",
+            expr.id,
+            closure_type
+        );
 
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
-        let sig = sig.map_bound(|sig| self.tcx.mk_fn_sig(
-            iter::once(self.tcx.intern_tup(sig.inputs(), false)),
-            sig.output(),
-            sig.variadic,
-            sig.unsafety,
-            sig.abi
-        ));
-
-        debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
-               expr_def_id,
-               sig,
-               opt_kind);
+        let sig = bound_sig.map_bound(|sig| {
+            self.tcx.mk_fn_sig(
+                iter::once(self.tcx.intern_tup(sig.inputs(), false)),
+                sig.output(),
+                sig.variadic,
+                sig.unsafety,
+                sig.abi,
+            )
+        });
+
+        debug!(
+            "check_closure: expr_def_id={:?}, sig={:?}, opt_kind={:?}",
+            expr_def_id,
+            sig,
+            opt_kind
+        );
 
         {
             let mut tables = self.tables.borrow_mut();
@@ -123,22 +149,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         closure_type
     }
 
-    fn deduce_expectations_from_expected_type
-        (&self,
-         expected_ty: Ty<'tcx>)
-         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
-        debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
-               expected_ty);
+    fn deduce_expectations_from_expected_type(
+        &self,
+        expected_ty: Ty<'tcx>,
+    ) -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
+        debug!(
+            "deduce_expectations_from_expected_type(expected_ty={:?})",
+            expected_ty
+        );
 
         match expected_ty.sty {
             ty::TyDynamic(ref object_type, ..) => {
-                let sig = object_type.projection_bounds()
+                let sig = object_type
+                    .projection_bounds()
                     .filter_map(|pb| {
                         let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
                         self.deduce_sig_from_projection(&pb)
                     })
                     .next();
-                let kind = object_type.principal()
+                let kind = object_type
+                    .principal()
                     .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id()));
                 (sig, kind)
             }
@@ -148,19 +178,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn deduce_expectations_from_obligations
-        (&self,
-         expected_vid: ty::TyVid)
-         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
+    fn deduce_expectations_from_obligations(
+        &self,
+        expected_vid: ty::TyVid,
+    ) -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
         let fulfillment_cx = self.fulfillment_cx.borrow();
         // Here `expected_ty` is known to be a type inference variable.
 
-        let expected_sig = fulfillment_cx.pending_obligations()
+        let expected_sig = fulfillment_cx
+            .pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
-                debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
-                       obligation.predicate);
+                debug!(
+                    "deduce_expectations_from_obligations: obligation.predicate={:?}",
+                    obligation.predicate
+                );
 
                 match obligation.predicate {
                     // Given a Projection predicate, we can potentially infer
@@ -179,7 +212,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // infer the kind. This can occur if there is a trait-reference
         // like `F : Fn<A>`. Note that due to subtyping we could encounter
         // many viable options, so pick the most restrictive.
-        let expected_kind = fulfillment_cx.pending_obligations()
+        let expected_kind = fulfillment_cx
+            .pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
@@ -204,20 +238,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // inference variable.
                     ty::Predicate::ClosureKind(..) => None,
                 };
-                opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
+                opt_trait_ref
+                    .and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
                     .and_then(|tr| self.tcx.lang_items().fn_trait_kind(tr.def_id()))
             })
-            .fold(None,
-                  |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
+            .fold(None, |best, cur| {
+                Some(best.map_or(cur, |best| cmp::min(best, cur)))
+            });
 
         (expected_sig, expected_kind)
     }
 
     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
     /// everything we need to know about a closure.
-    fn deduce_sig_from_projection(&self,
-                                  projection: &ty::PolyProjectionPredicate<'tcx>)
-                                  -> Option<ty::FnSig<'tcx>> {
+    fn deduce_sig_from_projection(
+        &self,
+        projection: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<ty::FnSig<'tcx>> {
         let tcx = self.tcx;
 
         debug!("deduce_sig_from_projection({:?})", projection);
@@ -230,8 +267,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let arg_param_ty = trait_ref.substs().type_at(1);
         let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
-        debug!("deduce_sig_from_projection: arg_param_ty {:?}",
-               arg_param_ty);
+        debug!(
+            "deduce_sig_from_projection: arg_param_ty {:?}",
+            arg_param_ty
+        );
 
         let input_tys = match arg_param_ty.sty {
             ty::TyTuple(tys, _) => tys.into_iter(),
@@ -242,31 +281,291 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let ret_param_ty = projection.0.ty;
         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
-        debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
+        debug!(
+            "deduce_sig_from_projection: ret_param_ty {:?}",
+            ret_param_ty
+        );
 
         let fn_sig = self.tcx.mk_fn_sig(
             input_tys.cloned(),
             ret_param_ty,
             false,
             hir::Unsafety::Normal,
-            Abi::Rust
+            Abi::Rust,
         );
         debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
 
         Some(fn_sig)
     }
 
-    fn self_type_matches_expected_vid(&self,
-                                      trait_ref: ty::PolyTraitRef<'tcx>,
-                                      expected_vid: ty::TyVid)
-                                      -> Option<ty::PolyTraitRef<'tcx>> {
+    fn self_type_matches_expected_vid(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        expected_vid: ty::TyVid,
+    ) -> Option<ty::PolyTraitRef<'tcx>> {
         let self_ty = self.shallow_resolve(trait_ref.self_ty());
-        debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
-               trait_ref,
-               self_ty);
+        debug!(
+            "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
+            trait_ref,
+            self_ty
+        );
         match self_ty.sty {
             ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
             _ => None,
         }
     }
+
+    fn sig_of_closure(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+        expected_sig: Option<ty::FnSig<'tcx>>,
+    ) -> ClosureSignatures<'tcx> {
+        if let Some(e) = expected_sig {
+            self.sig_of_closure_with_expectation(expr_def_id, decl, body, e)
+        } else {
+            self.sig_of_closure_no_expectation(expr_def_id, decl, body)
+        }
+    }
+
+    /// If there is no expected signature, then we will convert the
+    /// types that the user gave into a signature.
+    fn sig_of_closure_no_expectation(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+    ) -> ClosureSignatures<'tcx> {
+        debug!("sig_of_closure_no_expectation()");
+
+        let bound_sig = self.supplied_sig_of_closure(decl);
+
+        self.closure_sigs(expr_def_id, body, bound_sig)
+    }
+
+    /// Invoked to compute the signature of a closure expression. This
+    /// combines any user-provided type annotations (e.g., `|x: u32|
+    /// -> u32 { .. }`) with the expected signature.
+    ///
+    /// The approach is as follows:
+    ///
+    /// - Let `S` be the (higher-ranked) signature that we derive from the user's annotations.
+    /// - Let `E` be the (higher-ranked) signature that we derive from the expectations, if any.
+    ///   - If we have no expectation `E`, then the signature of the closure is `S`.
+    ///   - Otherwise, the signature of the closure is E. Moreover:
+    ///     - Skolemize the late-bound regions in `E`, yielding `E'`.
+    ///     - Instantiate all the late-bound regions bound in the closure within `S`
+    ///       with fresh (existential) variables, yielding `S'`
+    ///     - Require that `E' = S'`
+    ///       - We could use some kind of subtyping relationship here,
+    ///         I imagine, but equality is easier and works fine for
+    ///         our purposes.
+    ///
+    /// The key intuition here is that the user's types must be valid
+    /// from "the inside" of the closure, but the expectation
+    /// ultimately drives the overall signature.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// fn with_closure<F>(_: F)
+    ///   where F: Fn(&u32) -> &u32 { .. }
+    ///
+    /// with_closure(|x: &u32| { ... })
+    /// ```
+    ///
+    /// Here:
+    /// - E would be `fn(&u32) -> &u32`.
+    /// - S would be `fn(&u32) ->
+    /// - E' is `&'!0 u32 -> &'!0 u32`
+    /// - S' is `&'?0 u32 -> ?T`
+    ///
+    /// S' can be unified with E' with `['?0 = '!0, ?T = &'!10 u32]`.
+    ///
+    /// # Arguments
+    ///
+    /// - `expr_def_id`: the def-id of the closure expression
+    /// - `decl`: the HIR declaration of the closure
+    /// - `body`: the body of the closure
+    /// - `expected_sig`: the expected signature (if any). Note that
+    ///   this is missing a binder: that is, there may be late-bound
+    ///   regions with depth 1, which are bound then by the closure.
+    fn sig_of_closure_with_expectation(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+        expected_sig: ty::FnSig<'tcx>,
+    ) -> ClosureSignatures<'tcx> {
+        debug!(
+            "sig_of_closure_with_expectation(expected_sig={:?})",
+            expected_sig
+        );
+
+        // Watch out for some surprises and just ignore the
+        // expectation if things don't see to match up with what we
+        // expect.
+        if expected_sig.variadic != decl.variadic {
+            return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
+        } else if expected_sig.inputs_and_output.len() != decl.inputs.len() + 1 {
+            // we could probably handle this case more gracefully
+            return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
+        }
+
+        // Create a `PolyFnSig`. Note the oddity that late bound
+        // regions appearing free in `expected_sig` are now bound up
+        // in this binder we are creating.
+        assert!(!expected_sig.has_regions_escaping_depth(1));
+        let bound_sig = ty::Binder(self.tcx.mk_fn_sig(
+            expected_sig.inputs().iter().cloned(),
+            expected_sig.output(),
+            decl.variadic,
+            hir::Unsafety::Normal,
+            Abi::RustCall,
+        ));
+
+        // `deduce_expectations_from_expected_type` introduces
+        // late-bound lifetimes defined elsewhere, which we now
+        // anonymize away, so as not to confuse the user.
+        let bound_sig = self.tcx.anonymize_late_bound_regions(&bound_sig);
+
+        let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig);
+
+        // Up till this point, we have ignored the annotations that the user
+        // gave. This function will check that they unify successfully.
+        // Along the way, it also writes out entries for types that the user
+        // wrote into our tables, which are then later used by the privacy
+        // check.
+        match self.check_supplied_sig_against_expectation(decl, &closure_sigs) {
+            Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
+            Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body),
+        }
+
+        closure_sigs
+    }
+
+    /// Enforce the user's types against the expectation.  See
+    /// `sig_of_closure_with_expectation` for details on the overall
+    /// strategy.
+    fn check_supplied_sig_against_expectation(
+        &self,
+        decl: &hir::FnDecl,
+        expected_sigs: &ClosureSignatures<'tcx>,
+    ) -> InferResult<'tcx, ()> {
+        // Get the signature S that the user gave.
+        //
+        // (See comment on `sig_of_closure_with_expectation` for the
+        // meaning of these letters.)
+        let supplied_sig = self.supplied_sig_of_closure(decl);
+
+        debug!(
+            "check_supplied_sig_against_expectation: supplied_sig={:?}",
+            supplied_sig
+        );
+
+        // FIXME(#45727): As discussed in [this comment][c1], naively
+        // forcing equality here actually results in suboptimal error
+        // messages in some cases.  For now, if there would have been
+        // an obvious error, we fallback to declaring the type of the
+        // closure to be the one the user gave, which allows other
+        // error message code to trigger.
+        //
+        // However, I think [there is potential to do even better
+        // here][c2], since in *this* code we have the precise span of
+        // the type parameter in question in hand when we report the
+        // error.
+        //
+        // [c1]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341089706
+        // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796
+        self.infcx.commit_if_ok(|_| {
+            let mut all_obligations = vec![];
+
+            // The liberated version of this signature should be be a subtype
+            // of the liberated form of the expectation.
+            for ((hir_ty, &supplied_ty), expected_ty) in decl.inputs.iter()
+                           .zip(*supplied_sig.inputs().skip_binder()) // binder moved to (*) below
+                           .zip(expected_sigs.liberated_sig.inputs())
+            // `liberated_sig` is E'.
+            {
+                // Instantiate (this part of..) S to S', i.e., with fresh variables.
+                let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                    hir_ty.span,
+                    LateBoundRegionConversionTime::FnCall,
+                    &ty::Binder(supplied_ty),
+                ); // recreated from (*) above
+
+                // Check that E' = S'.
+                let cause = &self.misc(hir_ty.span);
+                let InferOk {
+                    value: (),
+                    obligations,
+                } = self.at(cause, self.param_env)
+                    .eq(*expected_ty, supplied_ty)?;
+                all_obligations.extend(obligations);
+            }
+
+            let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                decl.output.span(),
+                LateBoundRegionConversionTime::FnCall,
+                &supplied_sig.output(),
+            );
+            let cause = &self.misc(decl.output.span());
+            let InferOk {
+                value: (),
+                obligations,
+            } = self.at(cause, self.param_env)
+                .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
+            all_obligations.extend(obligations);
+
+            Ok(InferOk {
+                value: (),
+                obligations: all_obligations,
+            })
+        })
+    }
+
+    /// If there is no expected signature, then we will convert the
+    /// types that the user gave into a signature.
+    fn supplied_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> {
+        let astconv: &AstConv = self;
+
+        // First, convert the types that the user supplied (if any).
+        let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
+        let supplied_return = match decl.output {
+            hir::Return(ref output) => astconv.ast_ty_to_ty(&output),
+            hir::DefaultReturn(_) => astconv.ty_infer(decl.output.span()),
+        };
+
+        let result = ty::Binder(self.tcx.mk_fn_sig(
+            supplied_arguments,
+            supplied_return,
+            decl.variadic,
+            hir::Unsafety::Normal,
+            Abi::RustCall,
+        ));
+
+        debug!("supplied_sig_of_closure: result={:?}", result);
+
+        result
+    }
+
+    fn closure_sigs(
+        &self,
+        expr_def_id: DefId,
+        body: &hir::Body,
+        bound_sig: ty::PolyFnSig<'tcx>,
+    ) -> ClosureSignatures<'tcx> {
+        let liberated_sig = self.liberate_late_bound_regions(expr_def_id, &bound_sig);
+        let liberated_sig = self.inh.normalize_associated_types_in(
+            body.value.span,
+            body.value.id,
+            self.param_env,
+            &liberated_sig,
+        );
+        ClosureSignatures {
+            bound_sig,
+            liberated_sig,
+        }
+    }
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index a24f420af80..81e5b2fe00a 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -431,6 +431,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             ty::TySlice(_) => {
                 let lang_def_id = lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_u8_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 let lang_def_id = lang_items.const_ptr_impl();
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 26f7a7a3784..82d59ecfc92 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -100,7 +100,7 @@ use rustc::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 use require_c_abi_if_variadic;
 use session::{CompileIncomplete, Session};
 use TypeAndSubsts;
@@ -2467,7 +2467,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     if expected_count == 1 {""} else {"s"},
                     arg_count,
                     if arg_count == 1 {" was"} else {"s were"}),
-                error_code);
+                DiagnosticId::Error(error_code.to_owned()));
 
             if let Some(def_s) = def_span {
                 err.span_label(def_s, "defined here");
@@ -3448,6 +3448,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hir::QPath::TypeRelative(ref qself, _) => qself.span
         };
 
+        // Prohibit struct expressions when non exhaustive flag is set.
+        if let ty::TyAdt(adt, _) = struct_ty.sty {
+            if !adt.did.is_local() && adt.is_non_exhaustive() {
+                span_err!(self.tcx.sess, expr.span, E0639,
+                          "cannot create non-exhaustive {} using struct expression",
+                          adt.variant_descr());
+            }
+        }
+
         self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index ddbdd204305..483af08cabf 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -114,7 +114,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                 // FIXME(#27579) what amount of WF checking do we need for neg impls?
 
                 let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
-                if !tcx.trait_has_default_impl(trait_ref.def_id) {
+                if !tcx.trait_is_auto(trait_ref.def_id) {
                     error_192(tcx, item.span);
                 }
             }
@@ -318,7 +318,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
     fn check_trait(&mut self, item: &hir::Item) {
         let trait_def_id = self.tcx.hir.local_def_id(item.id);
 
-        if self.tcx.trait_has_default_impl(trait_def_id) {
+        if self.tcx.trait_is_auto(trait_def_id) {
             self.check_auto_trait(trait_def_id, item.span);
         }
 
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index c56a3b91ca3..569b6a2febb 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -137,6 +137,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
                                           "str",
                                           item.span);
             }
+            ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
+                self.check_primitive_impl(def_id,
+                                          lang_items.slice_u8_impl(),
+                                          "slice_u8",
+                                          "[u8]",
+                                          item.span);
+            }
             ty::TySlice(_) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_impl(),
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 6109fc57b0d..90a0952af04 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -132,7 +132,7 @@ pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     unsafety::check(tcx);
     orphan::check(tcx);
-    overlap::check_default_impls(tcx);
+    overlap::check_auto_impls(tcx);
 
     // these queries are executed for side-effects (error reporting):
     tcx.crate_inherent_impls(LOCAL_CRATE);
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index a5edc95b79b..9f183973621 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -100,11 +100,11 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
                 // This final impl is legal according to the orpan
                 // rules, but it invalidates the reasoning from
                 // `two_foos` above.
-                debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
+                debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
                        trait_ref,
                        trait_def_id,
-                       self.tcx.trait_has_default_impl(trait_def_id));
-                if self.tcx.trait_has_default_impl(trait_def_id) &&
+                       self.tcx.trait_is_auto(trait_def_id));
+                if self.tcx.trait_is_auto(trait_def_id) &&
                    !trait_def_id.is_local() {
                     let self_ty = trait_ref.self_ty();
                     let opt_self_def_id = match self_ty.sty {
@@ -142,7 +142,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
                     }
                 }
             }
-            hir::ItemDefaultImpl(_, ref item_trait_ref) => {
+            hir::ItemAutoImpl(_, ref item_trait_ref) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}",
                        self.tcx.hir.node_to_string(item.id));
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index 59ebae16d08..5cc6eaa5602 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -18,7 +18,7 @@ use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
-pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+pub fn check_auto_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut overlap = OverlapChecker { tcx };
 
     // this secondary walk specifically checks for some other cases,
@@ -74,19 +74,19 @@ struct OverlapChecker<'cx, 'tcx: 'cx> {
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemDefaultImpl(..) => {
-                // look for another default impl; note that due to the
+            hir::ItemAutoImpl(..) => {
+                // look for another auto impl; note that due to the
                 // general orphan/coherence rules, it must always be
                 // in this crate.
                 let impl_def_id = self.tcx.hir.local_def_id(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
 
-                let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
+                let prev_id = self.tcx.hir.trait_auto_impl(trait_ref.def_id).unwrap();
                 if prev_id != item.id {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                    self.tcx.span_of_impl(impl_def_id).unwrap(),
                                                    E0521,
-                                                   "redundant default implementations of trait \
+                                                   "redundant auto implementations of trait \
                                                     `{}`:",
                                                    trait_ref);
                     err.span_note(self.tcx
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 4672975d056..280fb04e040 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -84,7 +84,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemDefaultImpl(unsafety, _) => {
+            hir::ItemAutoImpl(unsafety, _) => {
                 self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
             }
             hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 75e864d07a6..81447097428 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -73,7 +73,7 @@ pub fn provide(providers: &mut Providers) {
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
-        is_default_impl,
+        is_auto_impl,
         ..*providers
     };
 }
@@ -273,7 +273,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemEnum(_, ref generics) |
                 ItemStruct(_, ref generics) |
                 ItemUnion(_, ref generics) => generics,
-                ItemTrait(_, ref generics, ..) => {
+                ItemTrait(_, _, ref generics, ..) => {
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_node_id {
                         result.predicates.push(ty::TraitRef {
@@ -425,7 +425,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         },
-        hir::ItemDefaultImpl(..) => {
+        hir::ItemAutoImpl(..) => {
             tcx.impl_trait_ref(def_id);
         }
         hir::ItemImpl(..) => {
@@ -670,7 +670,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     let (generics, bounds) = match item.node {
-        hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
+        hir::ItemTrait(.., ref generics, ref supertraits, _) => (generics, supertraits),
         _ => span_bug!(item.span,
                        "super_predicates invoked on non-trait"),
     };
@@ -713,7 +713,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let item = tcx.hir.expect_item(node_id);
 
     let unsafety = match item.node {
-        hir::ItemTrait(unsafety, ..) => unsafety,
+        hir::ItemTrait(_, unsafety, ..) => unsafety,
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
@@ -730,11 +730,14 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let def_path_hash = tcx.def_path_hash(def_id);
-    let has_default_impl = tcx.hir.trait_is_auto(def_id);
+    let is_auto = match item.node {
+        hir::ItemTrait(hir::IsAuto::Yes, ..) => true,
+        _ => tcx.hir.trait_is_auto(def_id),
+    };
     let def = ty::TraitDef::new(def_id,
                                 unsafety,
                                 paren_sugar,
-                                has_default_impl,
+                                is_auto,
                                 def_path_hash);
     tcx.alloc_trait_def(def)
 }
@@ -888,7 +891,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     generics
                 }
 
-                ItemTrait(_, ref generics, ..) => {
+                ItemTrait(_, _, ref generics, ..) => {
                     // Add in the self type parameter.
                     //
                     // Something of a hack: use the node id for the trait, also as
@@ -1074,7 +1077,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                ItemDefaultImpl(..) |
+                ItemAutoImpl(..) |
                 ItemTrait(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
@@ -1223,7 +1226,7 @@ fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     match tcx.hir.expect_item(node_id).node {
-        hir::ItemDefaultImpl(_, ref ast_trait_ref) => {
+        hir::ItemAutoImpl(_, ref ast_trait_ref) => {
             Some(AstConv::instantiate_mono_trait_ref(&icx,
                                                      ast_trait_ref,
                                                      tcx.mk_self_type()))
@@ -1350,7 +1353,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     generics
                 }
 
-                ItemTrait(_, ref generics, .., ref items) => {
+                ItemTrait(_, _, ref generics, .., ref items) => {
                     is_trait = Some((ty::TraitRef {
                         def_id,
                         substs: Substs::identity_for_item(tcx, def_id)
@@ -1665,13 +1668,13 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn is_default_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              def_id: DefId)
                              -> bool {
     match tcx.hir.get_if_local(def_id) {
-        Some(hir_map::NodeItem(&hir::Item { node: hir::ItemDefaultImpl(..), .. }))
+        Some(hir_map::NodeItem(&hir::Item { node: hir::ItemAutoImpl(..), .. }))
              => true,
         Some(_) => false,
-        _ => bug!("is_default_impl applied to non-local def-id {:?}", def_id)
+        _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
     }
 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 594cd0878cb..a23c7ded526 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1854,7 +1854,7 @@ unsafe impl !Clone for Foo { }
 
 This will compile:
 
-```
+```ignore (ignore auto_trait future compatibility warning)
 #![feature(optin_builtin_traits)]
 
 struct Foo;
@@ -4606,6 +4606,65 @@ foo.method(); // Ok!
 ```
 "##,
 
+E0638: r##"
+This error indicates that the struct or enum must be matched non-exhaustively
+as it has been marked as `non_exhaustive`.
+
+When applied within a crate, downstream users of the crate will need to use the
+`_` pattern when matching enums and use the `..` pattern when matching structs.
+
+For example, in the below example, since the enum is marked as
+`non_exhaustive`, it is required that downstream crates match non-exhaustively
+on it.
+
+```rust,ignore (pseudo-Rust)
+use std::error::Error as StdError;
+
+#[non_exhaustive] pub enum Error {
+   Message(String),
+   Other,
+}
+
+impl StdError for Error {
+   fn description(&self) -> &str {
+        // This will not error, despite being marked as non_exhaustive, as this
+        // enum is defined within the current crate, it can be matched
+        // exhaustively.
+        match *self {
+           Message(ref s) => s,
+           Other => "other or unknown error",
+        }
+   }
+}
+```
+
+An example of matching non-exhaustively on the above enum is provided below:
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Error;
+
+// This will not error as the non_exhaustive Error enum has been matched with a
+// wildcard.
+match error {
+   Message(ref s) => ...,
+   Other => ...,
+   _ => ...,
+}
+```
+
+Similarly, for structs, match with `..` to avoid this error.
+"##,
+
+E0639: r##"
+This error indicates that the struct or enum cannot be instantiated from
+outside of the defining crate as it has been marked as `non_exhaustive` and as
+such more fields/variants may be added in future that could cause adverse side
+effects for this code.
+
+It is recommended that you look for a `new` function or equivalent in the
+crate's documentation.
+"##,
+
 }
 
 register_diagnostics! {
@@ -4669,7 +4728,7 @@ register_diagnostics! {
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
-    E0521, // redundant default implementations of trait
+    E0521, // redundant auto implementations of trait
     E0533, // `{}` does not name a unit variant, unit struct or a constant
 //  E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
@@ -4684,4 +4743,5 @@ register_diagnostics! {
     E0627, // yield statement outside of generator literal
     E0632, // cannot provide explicit type parameters when `impl Trait` is used in
            // argument position.
+    E0641, // cannot cast to/from a pointer with an unknown kind
 }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 49ba0499f78..5227955d7b9 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -76,6 +76,7 @@ This API is completely unstable and subject to change.
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
+#![feature(match_default_bindings)]
 #![feature(never_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index e3ce403f3c1..915383d8189 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -15,6 +15,7 @@
 use std::mem;
 use std::fmt::{self, Write};
 use std::ops;
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 
 use syntax::symbol::Symbol;
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3a4dcc32173..9fb9437e1bc 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -292,10 +292,10 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         }
     }
 
-    // If this is a defaulted impl, then bail out early here
-    if tcx.is_default_impl(did) {
+    // If this is an auto impl, then bail out early here
+    if tcx.is_auto_impl(did) {
         return ret.push(clean::Item {
-            inner: clean::DefaultImplItem(clean::DefaultImpl {
+            inner: clean::AutoImplItem(clean::AutoImpl {
                 // FIXME: this should be decoded
                 unsafety: hir::Unsafety::Normal,
                 trait_: match associated_trait.as_ref().unwrap().clean(cx) {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f8fea643d5e..4b60536e1d1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -425,7 +425,7 @@ pub enum ItemEnum {
     PrimitiveItem(PrimitiveType),
     AssociatedConstItem(Type, Option<String>),
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
-    DefaultImplItem(DefaultImpl),
+    AutoImplItem(AutoImpl),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemEnum>),
 }
@@ -2733,12 +2733,12 @@ fn build_deref_target_impls(cx: &DocContext,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct DefaultImpl {
+pub struct AutoImpl {
     pub unsafety: hir::Unsafety,
     pub trait_: Type,
 }
 
-impl Clean<Item> for doctree::DefaultImpl {
+impl Clean<Item> for doctree::AutoImpl {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
             name: None,
@@ -2748,7 +2748,7 @@ impl Clean<Item> for doctree::DefaultImpl {
             visibility: Some(Public),
             stability: None,
             deprecation: None,
-            inner: DefaultImplItem(DefaultImpl {
+            inner: AutoImplItem(AutoImpl {
                 unsafety: self.unsafety,
                 trait_: self.trait_.clean(cx),
             }),
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 71594825cdb..c21bfd8842f 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -44,7 +44,7 @@ pub struct Module {
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub impls: Vec<Impl>,
-    pub def_traits: Vec<DefaultImpl>,
+    pub def_traits: Vec<AutoImpl>,
     pub foreigns: Vec<hir::ForeignMod>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
@@ -227,7 +227,7 @@ pub struct Impl {
     pub id: ast::NodeId,
 }
 
-pub struct DefaultImpl {
+pub struct AutoImpl {
     pub unsafety: hir::Unsafety,
     pub trait_: hir::TraitRef,
     pub id: ast::NodeId,
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index c9c5f01f0ae..c214c15ed4b 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -82,7 +82,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
             clean::PrimitiveItem(..)       => ItemType::Primitive,
             clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
-            clean::DefaultImplItem(..)     => ItemType::Impl,
+            clean::AutoImplItem(..)        => ItemType::Impl,
             clean::ForeignTypeItem         => ItemType::ForeignType,
             clean::StrippedItem(..)        => unreachable!(),
         }
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 79eaabe31e8..8c14d1bbe8f 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -105,7 +105,7 @@ r##"<!DOCTYPE html>
                     <dd>Switch tab</dd>
                     <dt>&#9166;</dt>
                     <dd>Go to active search result</dd>
-                    <dt>+</dt>
+                    <dt style="width:31px;">+ / -</dt>
                     <dd>Collapse/expand all sections</dd>
                 </dl>
             </div>
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 001e773098e..c132cf75e40 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -30,7 +30,6 @@
 use libc;
 use std::slice;
 
-use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index edd01a66075..eb59c57603a 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -34,6 +34,7 @@
 //! both occur before the crate is rendered.
 pub use self::ExternalLocation::*;
 
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::cmp::Ordering;
@@ -1325,7 +1326,7 @@ impl DocFolder for Cache {
                 // Figure out the id of this impl. This may map to a
                 // primitive rather than always to a struct/enum.
                 // Note: matching twice to restrict the lifetime of the `i` borrow.
-                let mut dids = vec![];
+                let mut dids = FxHashSet();
                 if let clean::Item { inner: clean::ImplItem(ref i), .. } = item {
                     let masked_trait = i.trait_.def_id().map_or(false,
                         |d| self.masked_crates.contains(&d.krate));
@@ -1335,7 +1336,7 @@ impl DocFolder for Cache {
                             clean::BorrowedRef {
                                 type_: box clean::ResolvedPath { did, .. }, ..
                             } => {
-                                dids.push(did);
+                                dids.insert(did);
                             }
                             ref t => {
                                 let did = t.primitive_type().and_then(|t| {
@@ -1343,7 +1344,7 @@ impl DocFolder for Cache {
                                 });
 
                                 if let Some(did) = did {
-                                    dids.push(did);
+                                    dids.insert(did);
                                 }
                             }
                         }
@@ -1352,7 +1353,7 @@ impl DocFolder for Cache {
                     if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
                         for bound in generics {
                             if let Some(did) = bound.def_id() {
-                                dids.push(did);
+                                dids.insert(did);
                             }
                         }
                     }
@@ -1929,7 +1930,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     document(w, cx, item)?;
 
     let mut indices = (0..items.len()).filter(|i| {
-        if let clean::DefaultImplItem(..) = items[*i].inner {
+        if let clean::AutoImplItem(..) = items[*i].inner {
             return false;
         }
         !items[*i].is_stripped()
@@ -2497,7 +2498,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
         if !foreign.is_empty() {
             write!(w, "
-                <h2 id='foreign-impls' class='section-header'>
+                <h2 id='foreign-impls' class='small-section-header'>
                   Implementations on Foreign Types<a href='#foreign-impls' class='anchor'></a>
                 </h2>
             ")?;
@@ -3590,7 +3591,8 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
             let mut links = HashSet::new();
             let ret = v.iter()
                        .filter_map(|i| if let Some(ref i) = i.inner_impl().trait_ {
-                           let out = format!("{:#}", i).replace("<", "&lt;").replace(">", "&gt;");
+                           let i_display = format!("{:#}", i);
+                           let out = Escape(&i_display);
                            let encoded = small_url_encode(&format!("{:#}", i));
                            let generated = format!("<a href=\"#impl-{}\">{}</a>", encoded, out);
                            if !links.contains(&generated) && links.insert(generated.clone()) {
@@ -3616,11 +3618,12 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
 fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
                   s: &clean::Struct) -> fmt::Result {
     let mut sidebar = String::new();
+    let fields = get_struct_fields_name(&s.fields);
 
-    if s.fields.iter()
-               .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) {
+    if !fields.is_empty() {
         if let doctree::Plain = s.struct_type {
-            sidebar.push_str("<li><a href=\"#fields\">Fields</a></li>");
+            sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+                                       <div class=\"sidebar-links\">{}</div>", fields));
         }
     }
 
@@ -3632,40 +3635,122 @@ fn sidebar_struct(fmt: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> {
+    match item.inner {
+        clean::ItemEnum::ImplItem(ref i) => {
+            if let Some(ref trait_) = i.trait_ {
+                Some((format!("{:#}", i.for_), format!("{:#}", trait_)))
+            } else {
+                None
+            }
+        },
+        _ => None,
+    }
+}
+
 fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
                  t: &clean::Trait) -> fmt::Result {
     let mut sidebar = String::new();
 
-    let has_types = t.items.iter().any(|m| m.is_associated_type());
-    let has_consts = t.items.iter().any(|m| m.is_associated_const());
-    let has_required = t.items.iter().any(|m| m.is_ty_method());
-    let has_provided = t.items.iter().any(|m| m.is_method());
+    let types = t.items
+                 .iter()
+                 .filter_map(|m| {
+                     match m.name {
+                         Some(ref name) if m.is_associated_type() => {
+                             Some(format!("<a href=\"#associatedtype.{name}\">{name}</a>",
+                                          name=name))
+                         }
+                         _ => None,
+                     }
+                 })
+                 .collect::<String>();
+    let consts = t.items
+                  .iter()
+                  .filter_map(|m| {
+                      match m.name {
+                          Some(ref name) if m.is_associated_const() => {
+                              Some(format!("<a href=\"#associatedconstant.{name}\">{name}</a>",
+                                           name=name))
+                          }
+                          _ => None,
+                      }
+                  })
+                  .collect::<String>();
+    let required = t.items
+                    .iter()
+                    .filter_map(|m| {
+                        match m.name {
+                            Some(ref name) if m.is_ty_method() => {
+                                Some(format!("<a href=\"#tymethod.{name}\">{name}</a>",
+                                             name=name))
+                            }
+                            _ => None,
+                        }
+                    })
+                    .collect::<String>();
+    let provided = t.items
+                    .iter()
+                    .filter_map(|m| {
+                        match m.name {
+                            Some(ref name) if m.is_method() => {
+                                Some(format!("<a href=\"#method.{name}\">{name}</a>", name=name))
+                            }
+                            _ => None,
+                        }
+                    })
+                    .collect::<String>();
 
-    if has_types {
-        sidebar.push_str("<li><a href=\"#associated-types\">Associated Types</a></li>");
+    if !types.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#associated-types\">\
+                                   Associated Types</a><div class=\"sidebar-links\">{}</div>",
+                                  types));
     }
-    if has_consts {
-        sidebar.push_str("<li><a href=\"#associated-const\">Associated Constants</a></li>");
+    if !consts.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#associated-const\">\
+                                   Associated Constants</a><div class=\"sidebar-links\">{}</div>",
+                                  consts));
     }
-    if has_required {
-        sidebar.push_str("<li><a href=\"#required-methods\">Required Methods</a></li>");
+    if !required.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#required-methods\">\
+                                   Required Methods</a><div class=\"sidebar-links\">{}</div>",
+                                  required));
     }
-    if has_provided {
-        sidebar.push_str("<li><a href=\"#provided-methods\">Provided Methods</a></li>");
+    if !provided.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#provided-methods\">\
+                                   Provided Methods</a><div class=\"sidebar-links\">{}</div>",
+                                  provided));
     }
 
     let c = cache();
 
     if let Some(implementors) = c.implementors.get(&it.def_id) {
-        if implementors.iter().any(|i| i.impl_.for_.def_id()
-                                   .map_or(false, |d| !c.paths.contains_key(&d)))
-        {
-            sidebar.push_str("<li><a href=\"#foreign-impls\">\
-                             Implementations on Foreign Types</a></li>");
-        }
-    }
-
-    sidebar.push_str("<li><a href=\"#implementors\">Implementors</a></li>");
+        let res = implementors.iter()
+                              .filter(|i| i.impl_.for_.def_id()
+                                                      .map_or(false, |d| !c.paths.contains_key(&d)))
+                              .filter_map(|i| {
+                                  if let Some(item) = implementor2item(&c, i) {
+                                      match extract_for_impl_name(&item) {
+                                          Some((ref name, ref url)) => {
+                                              Some(format!("<a href=\"#impl-{}\">{}</a>",
+                                                           small_url_encode(url),
+                                                           Escape(name)))
+                                          }
+                                          _ => None,
+                                      }
+                                  } else {
+                                      None
+                                  }
+                              })
+                              .collect::<String>();
+        if !res.is_empty() {
+            sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#foreign-impls\">\
+                                       Implementations on Foreign Types</a><div \
+                                       class=\"sidebar-links\">{}</div>",
+                                      res));
+        }
+    }
+
+    sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
 
     sidebar.push_str(&sidebar_assoc_items(it));
 
@@ -3692,13 +3777,29 @@ fn sidebar_typedef(fmt: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+fn get_struct_fields_name(fields: &[clean::Item]) -> String {
+    fields.iter()
+          .filter(|f| if let clean::StructFieldItem(..) = f.inner {
+              true
+          } else {
+              false
+          })
+          .filter_map(|f| match f.name {
+              Some(ref name) => Some(format!("<a href=\"#structfield.{name}\">\
+                                              {name}</a>", name=name)),
+              _ => None,
+          })
+          .collect()
+}
+
 fn sidebar_union(fmt: &mut fmt::Formatter, it: &clean::Item,
                  u: &clean::Union) -> fmt::Result {
     let mut sidebar = String::new();
+    let fields = get_struct_fields_name(&u.fields);
 
-    if u.fields.iter()
-               .any(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false }) {
-        sidebar.push_str("<li><a href=\"#fields\">Fields</a></li>");
+    if !fields.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
+                                   <div class=\"sidebar-links\">{}</div>", fields));
     }
 
     sidebar.push_str(&sidebar_assoc_items(it));
@@ -3713,8 +3814,16 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
                 e: &clean::Enum) -> fmt::Result {
     let mut sidebar = String::new();
 
-    if !e.variants.is_empty() {
-        sidebar.push_str("<li><a href=\"#variants\">Variants</a></li>");
+    let variants = e.variants.iter()
+                             .filter_map(|v| match v.name {
+                                 Some(ref name) => Some(format!("<a href=\"#variant.{name}\">{name}\
+                                                                 </a>", name = name)),
+                                 _ => None,
+                             })
+                             .collect::<String>();
+    if !variants.is_empty() {
+        sidebar.push_str(&format!("<a class=\"sidebar-title\" href=\"#variants\">Variants</a>\
+                                   <div class=\"sidebar-links\">{}</div>", variants));
     }
 
     sidebar.push_str(&sidebar_assoc_items(it));
@@ -3744,7 +3853,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
                    ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
                    ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
         if items.iter().any(|it| {
-            if let clean::DefaultImplItem(..) = it.inner {
+            if let clean::AutoImplItem(..) = it.inner {
                 false
             } else {
                 !it.is_stripped() && it.type_() == myty
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 04bf466a780..1d9bfa260bf 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -213,6 +213,7 @@
             break;
 
         case "+":
+        case "-":
             ev.preventDefault();
             toggleAllDocs();
             break;
@@ -349,7 +350,7 @@
             var valLower = query.query.toLowerCase(),
                 val = valLower,
                 typeFilter = itemTypeFromName(query.type),
-                results = [],
+                results = {},
                 split = valLower.split("::");
 
             // remove empty keywords
@@ -360,15 +361,52 @@
                 }
             }
 
+            function min(a, b) {
+                if (a < b) {
+                    return a;
+                }
+                return b;
+            }
+
+            function nbElements(obj) {
+                var size = 0, key;
+                for (key in obj) {
+                    if (obj.hasOwnProperty(key)) {
+                        size += 1;
+                    }
+                }
+                return size;
+            }
+
             function findArg(obj, val) {
+                var lev_distance = MAX_LEV_DISTANCE + 1;
                 if (obj && obj.type && obj.type.inputs.length > 0) {
                     for (var i = 0; i < obj.type.inputs.length; i++) {
                         if (obj.type.inputs[i].name === val) {
-                            return true;
+                            // No need to check anything else: we found it. Let's just move on.
+                            return 0;
+                        }
+                        lev_distance = min(levenshtein(obj.type.inputs[i].name, val), lev_distance);
+                        if (lev_distance === 0) {
+                            return 0;
                         }
                     }
                 }
-                return false;
+                return lev_distance;
+            }
+
+            function checkReturned(obj, val) {
+                var lev_distance = MAX_LEV_DISTANCE + 1;
+                if (obj && obj.type && obj.type.output) {
+                    if (obj.type.output.name.toLowerCase() === val) {
+                        return 0;
+                    }
+                    lev_distance = min(levenshtein(obj.type.output.name, val));
+                    if (lev_distance === 0) {
+                        return 0;
+                    }
+                }
+                return lev_distance;
             }
 
             function typePassesFilter(filter, type) {
@@ -398,22 +436,27 @@
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
-                val = val.substr(1, val.length - 2);
+                val = val.substr(1, val.length - 2).toLowerCase();
                 for (var i = 0; i < nSearchWords; ++i) {
+                    var ty = searchIndex[i];
                     if (searchWords[i] === val) {
                         // filter type: ... queries
                         if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                            results.push({id: i, index: -1});
+                            results[ty.path + ty.name] = {id: i, index: -1};
                         }
-                    } else if (findArg(searchIndex[i], val.toLowerCase()) ||
-                               (searchIndex[i].type &&
-                                searchIndex[i].type.output &&
-                                searchIndex[i].type.output.name === val.toLowerCase())) {
+                    } else if (findArg(searchIndex[i], val) ||
+                               (ty.type &&
+                                ty.type.output &&
+                                ty.type.output.name === val)) {
                         if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                            results.push({id: i, index: -1, dontValidate: true});
+                            results[ty.path + ty.name] = {
+                                id: i,
+                                index: -1,
+                                dontValidate: true,
+                            };
                         }
                     }
-                    if (results.length === max) {
+                    if (nbElements(results) === max) {
                         break;
                     }
                 }
@@ -431,6 +474,7 @@
 
                 for (var i = 0; i < nSearchWords; ++i) {
                     var type = searchIndex[i].type;
+                    var ty = searchIndex[i];
                     if (!type) {
                         continue;
                     }
@@ -444,7 +488,7 @@
                     var typeOutput = type.output ? type.output.name : "";
                     if (output === "*" || output == typeOutput) {
                         if (input === "*") {
-                            results.push({id: i, index: -1, dontValidate: true});
+                            results[ty.path + ty.name] = {id: i, index: -1, dontValidate: true};
                         } else {
                             var allFound = true;
                             for (var it = 0; allFound === true && it < inputs.length; it++) {
@@ -455,7 +499,11 @@
                                 allFound = found;
                             }
                             if (allFound === true) {
-                                results.push({id: i, index: -1, dontValidate: true});
+                                results[ty.path + ty.name] = {
+                                    id: i,
+                                    index: -1,
+                                    dontValidate: true,
+                                };
                             }
                         }
                     }
@@ -471,46 +519,77 @@
                 for (var i = 0; i < split.length; ++i) {
                     for (var j = 0; j < nSearchWords; ++j) {
                         var lev_distance;
+                        var ty = searchIndex[j];
+                        if (!ty) {
+                            continue;
+                        }
                         if (searchWords[j].indexOf(split[i]) > -1 ||
                             searchWords[j].indexOf(val) > -1 ||
                             searchWords[j].replace(/_/g, "").indexOf(val) > -1)
                         {
                             // filter type: ... queries
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
+                                results[ty.path + ty.name] = {
                                     id: j,
                                     index: searchWords[j].replace(/_/g, "").indexOf(val),
                                     lev: 0,
-                                });
+                                };
                             }
                         } else if (
-                            (lev_distance = levenshtein(searchWords[j], val)) <=
-                                MAX_LEV_DISTANCE) {
+                            (lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
-                                    id: j,
-                                    index: 0,
-                                    // we want lev results to go lower than others
-                                    lev: lev_distance,
-                                });
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
                             }
-                        } else if (findArg(searchIndex[j], val)) {
+                        } else if (
+                            (lev_distance = findArg(searchIndex[j], val)) <= MAX_LEV_DISTANCE) {
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
-                                    id: j,
-                                    index: 0,
-                                    // we want lev results to go lower than others
-                                    lev: lev_distance,
-                                });
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
+                            }
+                        } else if (
+                            (lev_distance = checkReturned(searchIndex[j], val)) <=
+                            MAX_LEV_DISTANCE) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
                             }
                         }
-                        if (results.length === max) {
+                        if (nbElements(results) === max) {
                             break;
                         }
                     }
                 }
             }
 
+            var ar = [];
+            for (var entry in results) {
+                if (results.hasOwnProperty(entry)) {
+                    ar.push(results[entry]);
+                }
+            }
+            results = ar;
             var nresults = results.length;
             for (var i = 0; i < nresults; ++i) {
                 results[i].word = searchWords[results[i].id];
@@ -586,16 +665,6 @@
                 return 0;
             });
 
-            // remove duplicates, according to the data provided
-            for (var i = results.length - 1; i > 0; i -= 1) {
-                if (results[i].word === results[i - 1].word &&
-                    results[i].item.ty === results[i - 1].item.ty &&
-                    results[i].item.path === results[i - 1].item.path &&
-                    (results[i].item.parent || {}).name === (results[i - 1].item.parent || {}).name)
-                {
-                    results[i].id = -1;
-                }
-            }
             for (var i = 0; i < results.length; ++i) {
                 var result = results[i],
                     name = result.item.name.toLowerCase(),
@@ -884,6 +953,7 @@
             elems[0].onclick = function() { printTab(0); };
             elems[1].onclick = function() { printTab(1); };
             elems[2].onclick = function() { printTab(2); };
+            printTab(currentTab);
         }
 
         function search(e) {
@@ -951,7 +1021,8 @@
                         }
                     }
                     if (results['others'].length < maxResults &&
-                        ((query.search && obj.name.indexOf(query.search)) || added === false)) {
+                        ((query.search && obj.name.indexOf(query.search) !== -1) ||
+                          added === false)) {
                         results['others'].push(obj);
                     }
                 }
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 398a692f8df..599b032b630 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -582,13 +582,14 @@ body.blur > :not(#help) {
 	display: block;
 	margin-top: -1px;
 }
-#help dd { margin: 5px 33px; }
+#help dd { margin: 5px 35px; }
 #help .infos { padding-left: 0; }
 #help h1, #help h2 { margin-top: 0; }
 #help > div div {
 	width: 50%;
 	float: left;
 	padding: 20px;
+	padding-left: 17px;
 }
 
 .stab {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 20da99a6b13..fcb25f7aef3 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -14,6 +14,7 @@
        html_playground_url = "https://play.rust-lang.org/")]
 #![deny(warnings)]
 
+#![feature(ascii_ctype)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -23,7 +24,6 @@
 #![feature(test)]
 #![feature(unicode)]
 #![feature(vec_remove_item)]
-#![feature(ascii_ctype)]
 
 extern crate arena;
 extern crate getopts;
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 959543404d8..77d97c84c99 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -116,7 +116,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             // handled in the `strip-priv-imports` pass
             clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
 
-            clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
+            clean::AutoImplItem(..) | clean::ImplItem(..) => {}
 
             // tymethods/macros have no control over privacy
             clean::MacroItem(..) | clean::TyMethodItem(..) => {}
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 9316805b932..9bbd16355be 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -337,15 +337,23 @@ pub fn make_test(s: &str,
 
     let mut prog = String::new();
 
-    // First push any outer attributes from the example, assuming they
-    // are intended to be crate attributes.
-    prog.push_str(&crate_attrs);
+    if opts.attrs.is_empty() {
+        // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
+        // lints that are commonly triggered in doctests. The crate-level test attributes are
+        // commonly used to make tests fail in case they trigger warnings, so having this there in
+        // that case may cause some tests to pass when they shouldn't have.
+        prog.push_str("#![allow(unused)]\n");
+    }
 
-    // Next, any attributes for other aspects such as lints.
+    // Next, any attributes that came from the crate root via #![doc(test(attr(...)))].
     for attr in &opts.attrs {
         prog.push_str(&format!("#![{}]\n", attr));
     }
 
+    // Now push any outer attributes from the example, assuming they
+    // are intended to be crate attributes.
+    prog.push_str(&crate_attrs);
+
     // Don't inject `extern crate std` because it's already injected by the
     // compiler.
     if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 327a330c2a2..b55076a01af 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -481,7 +481,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => {
+            hir::ItemTrait(_, unsafety, ref gen, ref b, ref item_ids) => {
                 let items = item_ids.iter()
                                     .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone())
                                     .collect();
@@ -532,10 +532,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     om.impls.push(i);
                 }
             },
-            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
                 // See comment above about ItemImpl.
                 if !self.inlining {
-                    let i = DefaultImpl {
+                    let i = AutoImpl {
                         unsafety,
                         trait_: trait_ref.clone(),
                         id: item.id,
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 5dd5f8953a0..d239b79d4ba 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -3,6 +3,9 @@ authors = ["The Rust Project Developers"]
 name = "std"
 version = "0.0.0"
 build = "build.rs"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/rust.git"
+description = "The Rust Standard Library"
 
 [lib]
 name = "std"
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index 327deb9b419..96d719c528c 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -38,8 +38,8 @@ use iter::FusedIterator;
 /// ```
 /// use std::ascii::AsciiExt;
 ///
-/// assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
-/// assert_eq!("café".to_ascii_uppercase(), "CAFé");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
 /// ```
 ///
 /// In the first example, the lowercased string is represented `"cafe\u{301}"`
@@ -60,19 +60,10 @@ pub trait AsciiExt {
 
     /// Checks if the value is within the ASCII range.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// assert!(int_ascii.is_ascii());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
 
@@ -86,19 +77,10 @@ pub trait AsciiExt {
     /// To uppercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_uppercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
+    /// # Note
     ///
-    /// assert_eq!('A', ascii.to_ascii_uppercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
-    /// assert_eq!(65, int_ascii.to_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
@@ -115,19 +97,10 @@ pub trait AsciiExt {
     /// To lowercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_lowercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'A';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 65;
-    ///
-    /// assert_eq!('a', ascii.to_ascii_lowercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
-    /// assert_eq!(97, int_ascii.to_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
@@ -139,20 +112,10 @@ pub trait AsciiExt {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii1 = 'A';
-    /// let ascii2 = 'a';
-    /// let ascii3 = 'A';
-    /// let ascii4 = 'z';
+    /// # Note
     ///
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii2));
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
-    /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 
@@ -164,17 +127,10 @@ pub trait AsciiExt {
     /// To return a new uppercased value without modifying the existing one, use
     /// [`to_ascii_uppercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let mut ascii = 'a';
-    ///
-    /// ascii.make_ascii_uppercase();
-    ///
-    /// assert_eq!('A', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -188,17 +144,10 @@ pub trait AsciiExt {
     /// To return a new lowercased value without modifying the existing one, use
     /// [`to_ascii_lowercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
+    /// # Note
     ///
-    /// let mut ascii = 'A';
-    ///
-    /// ascii.make_ascii_lowercase();
-    ///
-    /// assert_eq!('a', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -209,32 +158,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphabetic.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(A.is_ascii_alphabetic());
-    /// assert!(G.is_ascii_alphabetic());
-    /// assert!(a.is_ascii_alphabetic());
-    /// assert!(g.is_ascii_alphabetic());
-    /// assert!(!zero.is_ascii_alphabetic());
-    /// assert!(!percent.is_ascii_alphabetic());
-    /// assert!(!space.is_ascii_alphabetic());
-    /// assert!(!lf.is_ascii_alphabetic());
-    /// assert!(!esc.is_ascii_alphabetic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
@@ -243,32 +170,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII uppercase.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_uppercase());
-    /// assert!(G.is_ascii_uppercase());
-    /// assert!(!a.is_ascii_uppercase());
-    /// assert!(!g.is_ascii_uppercase());
-    /// assert!(!zero.is_ascii_uppercase());
-    /// assert!(!percent.is_ascii_uppercase());
-    /// assert!(!space.is_ascii_uppercase());
-    /// assert!(!lf.is_ascii_uppercase());
-    /// assert!(!esc.is_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
@@ -277,32 +182,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII lowercase.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_lowercase());
-    /// assert!(!G.is_ascii_lowercase());
-    /// assert!(a.is_ascii_lowercase());
-    /// assert!(g.is_ascii_lowercase());
-    /// assert!(!zero.is_ascii_lowercase());
-    /// assert!(!percent.is_ascii_lowercase());
-    /// assert!(!space.is_ascii_lowercase());
-    /// assert!(!lf.is_ascii_lowercase());
-    /// assert!(!esc.is_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
@@ -312,32 +195,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphanumeric.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_alphanumeric());
-    /// assert!(G.is_ascii_alphanumeric());
-    /// assert!(a.is_ascii_alphanumeric());
-    /// assert!(g.is_ascii_alphanumeric());
-    /// assert!(zero.is_ascii_alphanumeric());
-    /// assert!(!percent.is_ascii_alphanumeric());
-    /// assert!(!space.is_ascii_alphanumeric());
-    /// assert!(!lf.is_ascii_alphanumeric());
-    /// assert!(!esc.is_ascii_alphanumeric());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
@@ -346,32 +207,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII digits.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_digit());
-    /// assert!(!G.is_ascii_digit());
-    /// assert!(!a.is_ascii_digit());
-    /// assert!(!g.is_ascii_digit());
-    /// assert!(zero.is_ascii_digit());
-    /// assert!(!percent.is_ascii_digit());
-    /// assert!(!space.is_ascii_digit());
-    /// assert!(!lf.is_ascii_digit());
-    /// assert!(!esc.is_ascii_digit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
@@ -381,32 +220,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII hex digits.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_hexdigit());
-    /// assert!(!G.is_ascii_hexdigit());
-    /// assert!(a.is_ascii_hexdigit());
-    /// assert!(!g.is_ascii_hexdigit());
-    /// assert!(zero.is_ascii_hexdigit());
-    /// assert!(!percent.is_ascii_hexdigit());
-    /// assert!(!space.is_ascii_hexdigit());
-    /// assert!(!lf.is_ascii_hexdigit());
-    /// assert!(!esc.is_ascii_hexdigit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
@@ -420,32 +237,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_punctuation());
-    /// assert!(!G.is_ascii_punctuation());
-    /// assert!(!a.is_ascii_punctuation());
-    /// assert!(!g.is_ascii_punctuation());
-    /// assert!(!zero.is_ascii_punctuation());
-    /// assert!(percent.is_ascii_punctuation());
-    /// assert!(!space.is_ascii_punctuation());
-    /// assert!(!lf.is_ascii_punctuation());
-    /// assert!(!esc.is_ascii_punctuation());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
@@ -454,32 +249,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_graphic());
-    /// assert!(G.is_ascii_graphic());
-    /// assert!(a.is_ascii_graphic());
-    /// assert!(g.is_ascii_graphic());
-    /// assert!(zero.is_ascii_graphic());
-    /// assert!(percent.is_ascii_graphic());
-    /// assert!(!space.is_ascii_graphic());
-    /// assert!(!lf.is_ascii_graphic());
-    /// assert!(!esc.is_ascii_graphic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
@@ -505,32 +278,10 @@ pub trait AsciiExt {
     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_whitespace());
-    /// assert!(!G.is_ascii_whitespace());
-    /// assert!(!a.is_ascii_whitespace());
-    /// assert!(!g.is_ascii_whitespace());
-    /// assert!(!zero.is_ascii_whitespace());
-    /// assert!(!percent.is_ascii_whitespace());
-    /// assert!(space.is_ascii_whitespace());
-    /// assert!(lf.is_ascii_whitespace());
-    /// assert!(!esc.is_ascii_whitespace());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
@@ -539,36 +290,18 @@ pub trait AsciiExt {
     /// Note that most ASCII whitespace characters are control
     /// characters, but SPACE is not.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(!A.is_ascii_control());
-    /// assert!(!G.is_ascii_control());
-    /// assert!(!a.is_ascii_control());
-    /// assert!(!g.is_ascii_control());
-    /// assert!(!zero.is_ascii_control());
-    /// assert!(!percent.is_ascii_control());
-    /// assert!(!space.is_ascii_control());
-    /// assert!(lf.is_ascii_control());
-    /// assert!(esc.is_ascii_control());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[str]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for str {
     type Owned = String;
@@ -660,6 +393,10 @@ impl AsciiExt for str {
     }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[u8]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
@@ -753,201 +490,77 @@ impl AsciiExt for [u8] {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for u8 {
-    type Owned = u8;
-    #[inline]
-    fn is_ascii(&self) -> bool { *self & 128 == 0 }
-    #[inline]
-    fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
-    #[inline]
-    fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+macro_rules! impl_by_delegating {
+    ($ty:ty, $owned:ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl AsciiExt for $ty {
+            type Owned = $owned;
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii(&self) -> bool { self.is_ascii() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_uppercase(&self) -> Self::Owned { self.to_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_lowercase(&self) -> Self::Owned { self.to_ascii_lowercase() }
 
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o) }
 
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_uppercase(&mut self) { self.make_ascii_uppercase(); }
 
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|Lx|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_lowercase(&mut self) { self.make_ascii_lowercase(); }
 
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Ux|U|Lx|L|D|P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Cw|W => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            C|Cw => true,
-            _ => false
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for char {
-    type Owned = char;
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        *self as u32 <= 0x7F
-    }
+            #[inline]
+            fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
 
-    #[inline]
-    fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_uppercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
 
-    #[inline]
-    fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_lowercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
 
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &char) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
+            #[inline]
+            fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
 
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+            #[inline]
+            fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphabetic()
-    }
+            #[inline]
+            fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_uppercase()
-    }
+            #[inline]
+            fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_lowercase()
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphanumeric()
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_digit()
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_hexdigit()
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_punctuation()
+            #[inline]
+            fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
+        }
     }
+}
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_graphic()
-    }
+impl_by_delegating!(u8, u8);
+impl_by_delegating!(char, char);
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_whitespace()
-    }
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `[u8]` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `[u8]`.
+#[cfg(not(stage0))]
+impl_by_delegating!([u8], Vec<u8>);
 
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_control()
-    }
-}
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `str` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `str`.
+#[cfg(not(stage0))]
+impl_by_delegating!(str, String);
 
 /// An iterator over the escaped version of a byte.
 ///
@@ -1066,112 +679,11 @@ impl fmt::Debug for EscapeDefault {
 }
 
 
-static ASCII_LOWERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@',
-
-          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z',
-
-                      b'[', b'\\', b']', b'^', b'_',
-    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-static ASCII_UPPERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
-    b'`',
-
-          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z',
-
-                      b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-enum AsciiCharacterClass {
-    C,  // control
-    Cw, // control whitespace
-    W,  // whitespace
-    D,  // digit
-    L,  // lowercase
-    Lx, // lowercase hex digit
-    U,  // uppercase
-    Ux, // uppercase hex digit
-    P,  // punctuation
-}
-use self::AsciiCharacterClass::*;
-
-static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
-//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
-    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
-    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
-    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
-    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
-    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
-    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
-    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
-    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
-];
-
 #[cfg(test)]
 mod tests {
-    use super::*;
+    //! Note that most of these tests are not testing `AsciiExt` methods, but
+    //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
+    //! just using those methods, though.
     use char::from_u32;
 
     #[test]
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index f81adad3ebe..457c6e1409d 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -671,6 +671,10 @@ pub struct ArgsOs { inner: sys::args::Args }
 /// set to arbitrary text, and may not even exist. This means this property should
 /// not be relied upon for security purposes.
 ///
+/// On Unix systems shell usually expands unquoted arguments with glob patterns
+/// (such as `*` and `?`). On Windows this is not done, and such arguments are
+/// passed as-is.
+///
 /// # Panics
 ///
 /// The returned iterator will panic during iteration if any argument to the
diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs
index d76ab31862b..4d5e4df6f95 100644
--- a/src/libstd/heap.rs
+++ b/src/libstd/heap.rs
@@ -17,6 +17,7 @@ pub use alloc_system::System;
 
 #[cfg(not(test))]
 #[doc(hidden)]
+#[allow(unused_attributes)]
 pub mod __default_lib_allocator {
     use super::{System, Layout, Alloc, AllocErr};
     use ptr;
@@ -28,6 +29,7 @@ pub mod __default_lib_allocator {
     // ABI
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc(size: usize,
                                      align: usize,
                                      err: *mut u8) -> *mut u8 {
@@ -42,11 +44,13 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
         System.oom((*(err as *const AllocErr)).clone())
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -54,6 +58,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_usable_size(layout: *const u8,
                                            min: *mut usize,
                                            max: *mut usize) {
@@ -63,6 +68,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
                                        old_size: usize,
                                        old_align: usize,
@@ -81,6 +87,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
                                             align: usize,
                                             err: *mut u8) -> *mut u8 {
@@ -95,6 +102,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_excess(size: usize,
                                             align: usize,
                                             excess: *mut usize,
@@ -113,6 +121,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
                                               old_size: usize,
                                               old_align: usize,
@@ -135,6 +144,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
@@ -149,6 +159,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
                                                old_size: usize,
                                                old_align: usize,
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 4ebd3554fd1..6d3fbc9d268 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -147,6 +147,31 @@ impl<R: Read> BufReader<R> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
+    /// Returns `true` if there are no bytes in the internal buffer.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(bufreader_is_empty)]
+    /// use std::io::BufReader;
+    /// use std::io::BufRead;
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let f1 = File::open("log.txt")?;
+    /// let mut reader = BufReader::new(f1);
+    /// assert!(reader.is_empty());
+    ///
+    /// if reader.fill_buf()?.len() > 0 {
+    ///     assert!(!reader.is_empty());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+    pub fn is_empty(&self) -> bool {
+        self.pos == self.cap
+    }
+
     /// Unwraps this `BufReader`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 5cf1d225b90..429153dc58b 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -244,6 +244,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(align_offset)]
 #![feature(array_error_internals)]
+#![feature(ascii_ctype)]
 #![feature(asm)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 97b09b7e2ad..385076e50dd 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -188,6 +188,8 @@ pub struct AssertUnwindSafe<T>(
 // * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl UnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
@@ -221,6 +223,8 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
 // only thing which doesn't implement it (which then transitively applies to
 // everything else).
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl RefUnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 294743ed2cc..270878dc029 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -77,7 +77,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use ascii::*;
 use borrow::{Borrow, Cow};
 use cmp;
 use error::Error;
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 5555f364e6e..d59a0b65a69 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -10,7 +10,6 @@
 
 use cell::UnsafeCell;
 use fmt;
-use marker;
 use mem;
 use ops::{Deref, DerefMut};
 use ptr;
@@ -102,7 +101,10 @@ pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockReadGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockReadGuard<'a, T> {}
 
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
@@ -121,7 +123,10 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
+impl<'a, T: ?Sized> !Send for RwLockWriteGuard<'a, T> {}
+
+#[stable(feature = "rwlock_guard_sync", since = "1.23.0")]
+unsafe impl<'a, T: ?Sized + Sync> Sync for RwLockWriteGuard<'a, T> {}
 
 impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 3e631ad40ac..15f858bca16 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -20,7 +20,9 @@ use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
-/// Unix-specific extensions to `File`
+/// Unix-specific extensions to [`File`].
+///
+/// [`File`]: ../../../../std/fs/struct.File.html
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Reads a number of bytes starting from a given offset.
@@ -215,36 +217,282 @@ impl OpenOptionsExt for OpenOptions {
 // casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
+    /// Returns the ID of the device containing the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let dev_id = meta.dev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn dev(&self) -> u64;
+    /// Returns the inode number.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let inode = meta.ino();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ino(&self) -> u64;
+    /// Returns the rights applied to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let mode = meta.mode();
+    /// let user_has_write_access      = mode & 0o200;
+    /// let user_has_read_write_access = mode & 0o600;
+    /// let group_has_read_access      = mode & 0o040;
+    /// let others_have_exec_access    = mode & 0o001;
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mode(&self) -> u32;
+    /// Returns the number of hard links pointing to this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nb_hard_links = meta.nlink();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn nlink(&self) -> u64;
+    /// Returns the user ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let user_id = meta.uid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn uid(&self) -> u32;
+    /// Returns the group ID of the owner of this file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let group_id = meta.gid();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn gid(&self) -> u32;
+    /// Returns the device ID of this file (if it is a special one).
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let device_id = meta.rdev();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn rdev(&self) -> u64;
+    /// Returns the total size of this file in bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let file_size = meta.size();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn size(&self) -> u64;
+    /// Returns the time of the last access to the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_access_time = meta.atime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime(&self) -> i64;
+    /// Returns the time of the last access to the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_access_time = meta.atime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime_nsec(&self) -> i64;
+    /// Returns the time of the last modification of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_modification_time = meta.mtime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime(&self) -> i64;
+    /// Returns the time of the last modification of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_modification_time = meta.mtime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime_nsec(&self) -> i64;
+    /// Returns the time of the last status change of the file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let last_status_change_time = meta.ctime();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime(&self) -> i64;
+    /// Returns the time of the last status change of the file in nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let nano_last_status_change_time = meta.ctime_nsec();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime_nsec(&self) -> i64;
+    /// Returns the blocksize for filesystem I/O.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocksize = meta.blksize();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blksize(&self) -> u64;
+    /// Returns the number of blocks allocated to the file, in 512-byte units.
+    ///
+    /// Please note that this may be smaller than `st_size / 512` when the file has holes.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs;
+    /// use std::os::unix::fs::MetadataExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("some_file")?;
+    /// let blocks = meta.blocks();
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn blocks(&self) -> u64;
 }
@@ -269,19 +517,79 @@ impl MetadataExt for fs::Metadata {
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add special unix types (block/char device, fifo and socket)
+/// Add support for special unix types (block/char device, fifo and socket).
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("block_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_block_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_block_device(&self) -> bool;
     /// Returns whether this file type is a char device.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("char_device_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_char_device());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_char_device(&self) -> bool;
     /// Returns whether this file type is a fifo.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("fifo_file")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_fifo());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_fifo(&self) -> bool;
     /// Returns whether this file type is a socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::FileTypeExt;
+    ///
+    /// # use std::io;
+    /// # fn f() -> io::Result<()> {
+    /// let meta = fs::metadata("unix.socket")?;
+    /// let file_type = meta.file_type();
+    /// assert!(file_type.is_socket());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_socket(&self) -> bool;
 }
@@ -294,7 +602,9 @@ impl FileTypeExt for fs::FileType {
     fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
 }
 
-/// Unix-specific extension methods for `fs::DirEntry`
+/// Unix-specific extension methods for [`fs::DirEntry`].
+///
+/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
 pub trait DirEntryExt {
     /// Returns the underlying `d_ino` field in the contained `dirent`
@@ -354,7 +664,9 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 }
 
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for unix-specific options.
+/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 39e00270233..6e0cccff001 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -1228,7 +1228,7 @@ compat_fn! {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 mod gnu {
     use super::*;
 
@@ -1256,5 +1256,5 @@ mod gnu {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 pub use self::gnu::*;
diff --git a/src/libstd/sys/windows/path.rs b/src/libstd/sys/windows/path.rs
index 2b47808451b..98d62a0c953 100644
--- a/src/libstd/sys/windows/path.rs
+++ b/src/libstd/sys/windows/path.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
-
 use path::Prefix;
 use ffi::OsStr;
 use mem;
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 0d1766d5aec..631d69b05e1 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
+use ascii::AsciiExt;
 use collections::HashMap;
 use collections;
 use env::split_paths;
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 28a33c7ec14..ee49bf796b8 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -25,11 +25,15 @@
 //!
 //! Fatal logic errors in Rust cause *thread panic*, during which
 //! a thread will unwind the stack, running destructors and freeing
-//! owned resources. Thread panic is unrecoverable from within
-//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
-//! the panic may optionally be detected from a different thread. If
-//! the main thread panics, the application will exit with a non-zero
-//! exit code.
+//! owned resources. While not meant as a 'try/catch' mechanism, panics
+//! in Rust can nonetheless be caught (unless compiling with `panic=abort`) with
+//! [`catch_unwind`](../../std/panic/fn.catch_unwind.html) and recovered
+//! from, or alternatively be resumed with
+//! [`resume_unwind`](../../std/panic/fn.resume_unwind.html). If the panic
+//! is not caught the thread will exit, but the panic may optionally be
+//! detected from a different thread with [`join`]. If the main thread panics
+//! without the panic being caught, the application will exit with a
+//! non-zero exit code.
 //!
 //! When the main thread of a Rust program terminates, the entire program shuts
 //! down, even if other threads are still running. However, this module provides
diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs
index 5c0c7a4fbca..c012bdcb6db 100644
--- a/src/libstd_unicode/char.rs
+++ b/src/libstd_unicode/char.rs
@@ -923,6 +923,529 @@ impl char {
     pub fn to_uppercase(self) -> ToUppercase {
         ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
     }
+
+    /// Checks if the value is within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'a';
+    /// let non_ascii = '❤';
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        *self as u32 <= 0x7F
+    }
+
+    /// Makes a copy of the value in its ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// To uppercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'a';
+    /// let non_ascii = '❤';
+    ///
+    /// assert_eq!('A', ascii.to_ascii_uppercase());
+    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`to_uppercase`]: #method.to_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> char {
+        if self.is_ascii() {
+            (*self as u8).to_ascii_uppercase() as char
+        } else {
+            *self
+        }
+    }
+
+    /// Makes a copy of the value in its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// To lowercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'A';
+    /// let non_ascii = '❤';
+    ///
+    /// assert_eq!('a', ascii.to_ascii_lowercase());
+    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`to_lowercase`]: #method.to_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> char {
+        if self.is_ascii() {
+            (*self as u8).to_ascii_lowercase() as char
+        } else {
+            *self
+        }
+    }
+
+    /// Checks that two values are an ASCII case-insensitive match.
+    ///
+    /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let upper_a = 'A';
+    /// let lower_a = 'a';
+    /// let lower_z = 'z';
+    ///
+    /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
+    /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
+    /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &char) -> bool {
+        self.to_ascii_lowercase() == other.to_ascii_lowercase()
+    }
+
+    /// Converts this type to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut ascii = 'a';
+    ///
+    /// ascii.make_ascii_uppercase();
+    ///
+    /// assert_eq!('A', ascii);
+    /// ```
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        *self = self.to_ascii_uppercase();
+    }
+
+    /// Converts this type to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut ascii = 'A';
+    ///
+    /// ascii.make_ascii_lowercase();
+    ///
+    /// assert_eq!('a', ascii);
+    /// ```
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        *self = self.to_ascii_lowercase();
+    }
+
+    /// Checks if the value is an ASCII alphabetic character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_alphabetic());
+    /// assert!(uppercase_g.is_ascii_alphabetic());
+    /// assert!(a.is_ascii_alphabetic());
+    /// assert!(g.is_ascii_alphabetic());
+    /// assert!(!zero.is_ascii_alphabetic());
+    /// assert!(!percent.is_ascii_alphabetic());
+    /// assert!(!space.is_ascii_alphabetic());
+    /// assert!(!lf.is_ascii_alphabetic());
+    /// assert!(!esc.is_ascii_alphabetic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_alphabetic()
+    }
+
+    /// Checks if the value is an ASCII uppercase character:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_uppercase());
+    /// assert!(uppercase_g.is_ascii_uppercase());
+    /// assert!(!a.is_ascii_uppercase());
+    /// assert!(!g.is_ascii_uppercase());
+    /// assert!(!zero.is_ascii_uppercase());
+    /// assert!(!percent.is_ascii_uppercase());
+    /// assert!(!space.is_ascii_uppercase());
+    /// assert!(!lf.is_ascii_uppercase());
+    /// assert!(!esc.is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_uppercase()
+    }
+
+    /// Checks if the value is an ASCII lowercase character:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_lowercase());
+    /// assert!(!uppercase_g.is_ascii_lowercase());
+    /// assert!(a.is_ascii_lowercase());
+    /// assert!(g.is_ascii_lowercase());
+    /// assert!(!zero.is_ascii_lowercase());
+    /// assert!(!percent.is_ascii_lowercase());
+    /// assert!(!space.is_ascii_lowercase());
+    /// assert!(!lf.is_ascii_lowercase());
+    /// assert!(!esc.is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_lowercase()
+    }
+
+    /// Checks if the value is an ASCII alphanumeric character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_alphanumeric());
+    /// assert!(uppercase_g.is_ascii_alphanumeric());
+    /// assert!(a.is_ascii_alphanumeric());
+    /// assert!(g.is_ascii_alphanumeric());
+    /// assert!(zero.is_ascii_alphanumeric());
+    /// assert!(!percent.is_ascii_alphanumeric());
+    /// assert!(!space.is_ascii_alphanumeric());
+    /// assert!(!lf.is_ascii_alphanumeric());
+    /// assert!(!esc.is_ascii_alphanumeric());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_alphanumeric()
+    }
+
+    /// Checks if the value is an ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_digit());
+    /// assert!(!uppercase_g.is_ascii_digit());
+    /// assert!(!a.is_ascii_digit());
+    /// assert!(!g.is_ascii_digit());
+    /// assert!(zero.is_ascii_digit());
+    /// assert!(!percent.is_ascii_digit());
+    /// assert!(!space.is_ascii_digit());
+    /// assert!(!lf.is_ascii_digit());
+    /// assert!(!esc.is_ascii_digit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_digit()
+    }
+
+    /// Checks if the value is an ASCII hexadecimal digit:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_hexdigit());
+    /// assert!(!uppercase_g.is_ascii_hexdigit());
+    /// assert!(a.is_ascii_hexdigit());
+    /// assert!(!g.is_ascii_hexdigit());
+    /// assert!(zero.is_ascii_hexdigit());
+    /// assert!(!percent.is_ascii_hexdigit());
+    /// assert!(!space.is_ascii_hexdigit());
+    /// assert!(!lf.is_ascii_hexdigit());
+    /// assert!(!esc.is_ascii_hexdigit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_hexdigit()
+    }
+
+    /// Checks if the value is an ASCII punctuation character:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_punctuation());
+    /// assert!(!uppercase_g.is_ascii_punctuation());
+    /// assert!(!a.is_ascii_punctuation());
+    /// assert!(!g.is_ascii_punctuation());
+    /// assert!(!zero.is_ascii_punctuation());
+    /// assert!(percent.is_ascii_punctuation());
+    /// assert!(!space.is_ascii_punctuation());
+    /// assert!(!lf.is_ascii_punctuation());
+    /// assert!(!esc.is_ascii_punctuation());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_punctuation()
+    }
+
+    /// Checks if the value is an ASCII graphic character:
+    /// U+0021 '@' ... U+007E '~'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_graphic());
+    /// assert!(uppercase_g.is_ascii_graphic());
+    /// assert!(a.is_ascii_graphic());
+    /// assert!(g.is_ascii_graphic());
+    /// assert!(zero.is_ascii_graphic());
+    /// assert!(percent.is_ascii_graphic());
+    /// assert!(!space.is_ascii_graphic());
+    /// assert!(!lf.is_ascii_graphic());
+    /// assert!(!esc.is_ascii_graphic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_graphic()
+    }
+
+    /// Checks if the value is an ASCII whitespace character:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_whitespace());
+    /// assert!(!uppercase_g.is_ascii_whitespace());
+    /// assert!(!a.is_ascii_whitespace());
+    /// assert!(!g.is_ascii_whitespace());
+    /// assert!(!zero.is_ascii_whitespace());
+    /// assert!(!percent.is_ascii_whitespace());
+    /// assert!(space.is_ascii_whitespace());
+    /// assert!(lf.is_ascii_whitespace());
+    /// assert!(!esc.is_ascii_whitespace());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_whitespace()
+    }
+
+    /// Checks if the value is an ASCII control character:
+    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_control());
+    /// assert!(!uppercase_g.is_ascii_control());
+    /// assert!(!a.is_ascii_control());
+    /// assert!(!g.is_ascii_control());
+    /// assert!(!zero.is_ascii_control());
+    /// assert!(!percent.is_ascii_control());
+    /// assert!(!space.is_ascii_control());
+    /// assert!(lf.is_ascii_control());
+    /// assert!(esc.is_ascii_control());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_control()
+    }
 }
 
 /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index e5a114caed0..65058b6554a 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -30,6 +30,7 @@
 #![deny(warnings)]
 #![no_std]
 
+#![feature(ascii_ctype)]
 #![feature(core_char_ext)]
 #![feature(str_internals)]
 #![feature(decode_utf8)]
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index be0af8052eb..99dff4edaad 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1581,6 +1581,13 @@ impl FnDecl {
     }
 }
 
+/// Is the trait definition an auto trait?
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAuto {
+    Yes,
+    No
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1942,12 +1949,12 @@ pub enum ItemKind {
     Union(VariantData, Generics),
     /// A Trait declaration (`trait` or `pub trait`).
     ///
-    /// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
-    Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
+    /// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
+    Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
     /// Auto trait implementation.
     ///
     /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
-    DefaultImpl(Unsafety, TraitRef),
+    AutoImpl(Unsafety, TraitRef),
     /// An implementation.
     ///
     /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
@@ -1986,7 +1993,7 @@ impl ItemKind {
             ItemKind::Mac(..) |
             ItemKind::MacroDef(..) |
             ItemKind::Impl(..) |
-            ItemKind::DefaultImpl(..) => "item"
+            ItemKind::AutoImpl(..) => "item"
         }
     }
 }
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index dd46903bb88..3464db2a811 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -17,11 +17,15 @@
 //! within the CodeMap, which upon request can be converted to line and column
 //! information, source code snippets, etc.
 
+
 pub use syntax_pos::*;
 pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo, NameAndSpan};
 pub use self::ExpnFormat::*;
 
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::StableHasher;
 use std::cell::{RefCell, Ref};
+use std::hash::Hash;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
 
@@ -98,6 +102,24 @@ impl FileLoader for RealFileLoader {
     }
 }
 
+// This is a FileMap identifier that is used to correlate FileMaps between
+// subsequent compilation sessions (which is something we need to do during
+// incremental compilation).
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct StableFilemapId(u128);
+
+impl StableFilemapId {
+    pub fn new(filemap: &FileMap) -> StableFilemapId {
+        let mut hasher = StableHasher::new();
+
+        filemap.name.hash(&mut hasher);
+        filemap.name_was_remapped.hash(&mut hasher);
+        filemap.unmapped_path.hash(&mut hasher);
+
+        StableFilemapId(hasher.finish())
+    }
+}
+
 // _____________________________________________________________________________
 // CodeMap
 //
@@ -108,6 +130,7 @@ pub struct CodeMap {
     // This is used to apply the file path remapping as specified via
     // -Zremap-path-prefix to all FileMaps allocated within this CodeMap.
     path_mapping: FilePathMapping,
+    stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Rc<FileMap>>>,
 }
 
 impl CodeMap {
@@ -116,6 +139,7 @@ impl CodeMap {
             files: RefCell::new(Vec::new()),
             file_loader: Box::new(RealFileLoader),
             path_mapping,
+            stable_id_to_filemap: RefCell::new(FxHashMap()),
         }
     }
 
@@ -126,6 +150,7 @@ impl CodeMap {
             files: RefCell::new(Vec::new()),
             file_loader,
             path_mapping,
+            stable_id_to_filemap: RefCell::new(FxHashMap()),
         }
     }
 
@@ -146,6 +171,10 @@ impl CodeMap {
         self.files.borrow()
     }
 
+    pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option<Rc<FileMap>> {
+        self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone())
+    }
+
     fn next_start_pos(&self) -> usize {
         let files = self.files.borrow();
         match files.last() {
@@ -180,6 +209,10 @@ impl CodeMap {
 
         files.push(filemap.clone());
 
+        self.stable_id_to_filemap
+            .borrow_mut()
+            .insert(StableFilemapId::new(&filemap), filemap.clone());
+
         filemap
     }
 
@@ -209,7 +242,8 @@ impl CodeMap {
                                 src_hash: u128,
                                 source_len: usize,
                                 mut file_local_lines: Vec<BytePos>,
-                                mut file_local_multibyte_chars: Vec<MultiByteChar>)
+                                mut file_local_multibyte_chars: Vec<MultiByteChar>,
+                                mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
                                 -> Rc<FileMap> {
         let start_pos = self.next_start_pos();
         let mut files = self.files.borrow_mut();
@@ -225,6 +259,10 @@ impl CodeMap {
             mbc.pos = mbc.pos + start_pos;
         }
 
+        for swc in &mut file_local_non_narrow_chars {
+            *swc = *swc + start_pos;
+        }
+
         let filemap = Rc::new(FileMap {
             name: filename,
             name_was_remapped,
@@ -237,10 +275,15 @@ impl CodeMap {
             end_pos,
             lines: RefCell::new(file_local_lines),
             multibyte_chars: RefCell::new(file_local_multibyte_chars),
+            non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
         });
 
         files.push(filemap.clone());
 
+        self.stable_id_to_filemap
+            .borrow_mut()
+            .insert(StableFilemapId::new(&filemap), filemap.clone());
+
         filemap
     }
 
@@ -260,6 +303,24 @@ impl CodeMap {
                 let line = a + 1; // Line numbers start at 1
                 let linebpos = (*f.lines.borrow())[a];
                 let linechpos = self.bytepos_to_file_charpos(linebpos);
+                let col = chpos - linechpos;
+
+                let col_display = {
+                    let non_narrow_chars = f.non_narrow_chars.borrow();
+                    let start_width_idx = non_narrow_chars
+                        .binary_search_by_key(&linebpos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let end_width_idx = non_narrow_chars
+                        .binary_search_by_key(&pos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let special_chars = end_width_idx - start_width_idx;
+                    let non_narrow: usize =
+                        non_narrow_chars[start_width_idx..end_width_idx]
+                        .into_iter()
+                        .map(|x| x.width())
+                        .sum();
+                    col.0 - special_chars + non_narrow
+                };
                 debug!("byte pos {:?} is on the line at byte pos {:?}",
                        pos, linebpos);
                 debug!("char pos {:?} is on the line at char pos {:?}",
@@ -269,14 +330,28 @@ impl CodeMap {
                 Loc {
                     file: f,
                     line,
-                    col: chpos - linechpos,
+                    col,
+                    col_display,
                 }
             }
             Err(f) => {
+                let col_display = {
+                    let non_narrow_chars = f.non_narrow_chars.borrow();
+                    let end_width_idx = non_narrow_chars
+                        .binary_search_by_key(&pos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let non_narrow: usize =
+                        non_narrow_chars[0..end_width_idx]
+                        .into_iter()
+                        .map(|x| x.width())
+                        .sum();
+                    chpos.0 - end_width_idx + non_narrow
+                };
                 Loc {
                     file: f,
                     line: 0,
                     col: chpos,
+                    col_display,
                 }
             }
         }
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index e8ecf58072a..c01836b6194 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -18,7 +18,11 @@ macro_rules! register_diagnostic {
 macro_rules! span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_fatal_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_fatal_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -26,7 +30,11 @@ macro_rules! span_fatal {
 macro_rules! span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_err_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -34,7 +42,11 @@ macro_rules! span_err {
 macro_rules! span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_warn_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -42,7 +54,10 @@ macro_rules! span_warn {
 macro_rules! struct_err {
     ($session:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_err_with_code(&format!($($message)*), stringify!($code))
+        $session.struct_err_with_code(
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -51,9 +66,17 @@ macro_rules! span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
         if $is_warning {
-            $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+            $session.span_warn_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         } else {
-            $session.span_err_with_code($span, &format!($($message)*), stringify!($code))
+            $session.span_err_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         }
     })
 }
@@ -62,7 +85,11 @@ macro_rules! span_err_or_warn {
 macro_rules! struct_span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_fatal_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_fatal_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -70,7 +97,11 @@ macro_rules! struct_span_fatal {
 macro_rules! struct_span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -89,7 +120,11 @@ macro_rules! type_error_struct {
 macro_rules! struct_span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_warn_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -98,9 +133,17 @@ macro_rules! struct_span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
         if $is_warning {
-            $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+            $session.struct_span_warn_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         } else {
-            $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+            $session.struct_span_err_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         }
     })
 }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 30451ec757a..a69bf53ee14 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -35,7 +35,6 @@ use visit::{self, FnKind, Visitor};
 use parse::ParseSess;
 use symbol::Symbol;
 
-use std::ascii::AsciiExt;
 use std::env;
 
 macro_rules! set {
@@ -386,6 +385,9 @@ declare_features! (
     // allow '|' at beginning of match arms (RFC 1925)
     (active, match_beginning_vert, "1.21.0", Some(44101)),
 
+    // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
+    (active, non_exhaustive, "1.22.0", Some(44109)),
+
     // Copy/Clone closures (RFC 2132)
     (active, clone_closures, "1.22.0", Some(44490)),
     (active, copy_closures, "1.22.0", Some(44490)),
@@ -614,6 +616,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                              not yet settled",
                                             cfg_fn!(structural_match))),
 
+    // RFC #2008
+    ("non_exhaustive", Whitelisted, Gated(Stability::Unstable,
+                                          "non_exhaustive",
+                                          "non exhaustive is an experimental feature",
+                                          cfg_fn!(non_exhaustive))),
+
     ("plugin", CrateLevel, Gated(Stability::Unstable,
                                  "plugin",
                                  "compiler plugins are experimental \
@@ -908,6 +916,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                  "allow_fail attribute is currently unstable",
                                  cfg_fn!(allow_fail))),
 
+    ("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
+                                     "rustc_attrs",
+                                     "this is an internal attribute that will \
+                                      never be stable",
+                                     cfg_fn!(rustc_attrs))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
@@ -1357,10 +1371,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 }
             }
 
-            ast::ItemKind::DefaultImpl(..) => {
+            ast::ItemKind::AutoImpl(..) => {
                 gate_feature_post!(&self, optin_builtin_traits,
                                    i.span,
-                                   "default trait implementations are experimental \
+                                   "auto trait implementations are experimental \
                                     and possibly buggy");
             }
 
@@ -1389,6 +1403,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 }
             }
 
+            ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
+                gate_feature_post!(&self, optin_builtin_traits,
+                                   i.span,
+                                   "auto traits are experimental and possibly buggy");
+            }
+
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate_feature_post!(&self, decl_macro, i.span, msg);
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index fea49424dc8..cc63bffec48 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -908,8 +908,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             let generics = folder.fold_generics(generics);
             ItemKind::Union(folder.fold_variant_data(struct_def), generics)
         }
-        ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
-            ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
+        ItemKind::AutoImpl(unsafety, ref trait_ref) => {
+            ItemKind::AutoImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
         }
         ItemKind::Impl(unsafety,
                        polarity,
@@ -926,7 +926,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             folder.fold_ty(ty),
             impl_items.move_flat_map(|item| folder.fold_impl_item(item)),
         ),
-        ItemKind::Trait(unsafety, generics, bounds, items) => ItemKind::Trait(
+        ItemKind::Trait(is_auto, unsafety, generics, bounds, items) => ItemKind::Trait(
+            is_auto,
             unsafety,
             folder.fold_generics(generics),
             folder.fold_bounds(bounds),
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index b8151819bff..74a762f2f62 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -23,42 +23,48 @@ use codemap::{CodeMap, FilePathMapping};
 use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
 use errors::registry::Registry;
 use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::DiagnosticId;
 use errors::emitter::Emitter;
 
 use std::rc::Rc;
 use std::io::{self, Write};
 use std::vec;
 
-use rustc_serialize::json::as_json;
+use rustc_serialize::json::{as_json, as_pretty_json};
 
 pub struct JsonEmitter {
     dst: Box<Write + Send>,
     registry: Option<Registry>,
     cm: Rc<CodeMapper + 'static>,
+    pretty: bool,
 }
 
 impl JsonEmitter {
     pub fn stderr(registry: Option<Registry>,
-                  code_map: Rc<CodeMap>) -> JsonEmitter {
+                  code_map: Rc<CodeMap>,
+                  pretty: bool) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
             registry,
             cm: code_map,
+            pretty,
         }
     }
 
-    pub fn basic() -> JsonEmitter {
+    pub fn basic(pretty: bool) -> JsonEmitter {
         let file_path_mapping = FilePathMapping::empty();
-        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)))
+        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty)
     }
 
     pub fn new(dst: Box<Write + Send>,
                registry: Option<Registry>,
-               code_map: Rc<CodeMap>) -> JsonEmitter {
+               code_map: Rc<CodeMap>,
+               pretty: bool) -> JsonEmitter {
         JsonEmitter {
             dst,
             registry,
             cm: code_map,
+            pretty,
         }
     }
 }
@@ -66,7 +72,12 @@ impl JsonEmitter {
 impl Emitter for JsonEmitter {
     fn emit(&mut self, db: &DiagnosticBuilder) {
         let data = Diagnostic::from_diagnostic_builder(db, self);
-        if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
+        let result = if self.pretty {
+            writeln!(&mut self.dst, "{}", as_pretty_json(&data))
+        } else {
+            writeln!(&mut self.dst, "{}", as_json(&data))
+        };
+        if let Err(e) = result {
             panic!("failed to print diagnostics: {:?}", e);
         }
     }
@@ -84,9 +95,7 @@ struct Diagnostic {
     spans: Vec<DiagnosticSpan>,
     /// Associated diagnostic messages.
     children: Vec<Diagnostic>,
-    /// The message as rustc would render it. Currently this is only
-    /// `Some` for "suggestions", but eventually it will include all
-    /// snippets.
+    /// The message as rustc would render it. Currently this is always `None`
     rendered: Option<String>,
 }
 
@@ -109,9 +118,7 @@ struct DiagnosticSpan {
     /// Label that should be placed at this location (if any)
     label: Option<String>,
     /// If we are suggesting a replacement, this will contain text
-    /// that should be sliced in atop this span. You may prefer to
-    /// load the fully rendered version from the parent `Diagnostic`,
-    /// however.
+    /// that should be sliced in atop this span.
     suggested_replacement: Option<String>,
     /// Macro invocations that created the code at this span, if any.
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
@@ -340,9 +347,12 @@ impl DiagnosticSpanLine {
 }
 
 impl DiagnosticCode {
-    fn map_opt_string(s: Option<String>, je: &JsonEmitter) -> Option<DiagnosticCode> {
+    fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<DiagnosticCode> {
         s.map(|s| {
-
+            let s = match s {
+                DiagnosticId::Error(s) => s,
+                DiagnosticId::Lint(s) => s,
+            };
             let explanation = je.registry
                                 .as_ref()
                                 .and_then(|registry| registry.find_description(&s));
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index d9c3dbb630d..951163d35fa 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -433,6 +433,7 @@ impl<'a> StringReader<'a> {
                     self.filemap.record_multibyte_char(self.pos, new_ch_len);
                 }
             }
+            self.filemap.record_width(self.pos, new_ch);
         } else {
             self.ch = None;
             self.pos = new_pos;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a3a265450ab..6c6bcb2cc82 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -21,7 +21,7 @@ use ast::EnumDef;
 use ast::{Expr, ExprKind, RangeLimits};
 use ast::{Field, FnDecl};
 use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
-use ast::{Ident, ImplItem, Item, ItemKind};
+use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
 use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy};
 use ast::Local;
 use ast::MacStmtStyle;
@@ -974,11 +974,12 @@ impl<'a> Parser<'a> {
     pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
         let handler = self.diagnostic();
 
-        self.parse_seq_to_before_tokens(kets,
-                                        SeqSep::none(),
-                                        TokenExpectType::Expect,
-                                        |p| Ok(p.parse_token_tree()),
-                                        |mut e| handler.cancel(&mut e));
+        if let Err(ref mut err) = self.parse_seq_to_before_tokens(kets,
+                                                                  SeqSep::none(),
+                                                                  TokenExpectType::Expect,
+                                                                  |p| Ok(p.parse_token_tree())) {
+            handler.cancel(err);
+        }
     }
 
     /// Parse a sequence, including the closing delimiter. The function
@@ -991,7 +992,7 @@ impl<'a> Parser<'a> {
                                   -> PResult<'a, Vec<T>> where
         F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
     {
-        let val = self.parse_seq_to_before_end(ket, sep, f);
+        let val = self.parse_seq_to_before_end(ket, sep, f)?;
         self.bump();
         Ok(val)
     }
@@ -1003,22 +1004,19 @@ impl<'a> Parser<'a> {
                                          ket: &token::Token,
                                          sep: SeqSep,
                                          f: F)
-                                         -> Vec<T>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>
+                                         -> PResult<'a, Vec<T>>
+        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
     {
-        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f, |mut e| e.emit())
+        self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
     }
 
-    // `fe` is an error handler.
-    fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
+    fn parse_seq_to_before_tokens<T, F>(&mut self,
                                             kets: &[&token::Token],
                                             sep: SeqSep,
                                             expect: TokenExpectType,
-                                            mut f: F,
-                                            mut fe: Fe)
-                                            -> Vec<T>
-        where F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
-              Fe: FnMut(DiagnosticBuilder)
+                                            mut f: F)
+                                            -> PResult<'a, Vec<T>>
+        where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>
     {
         let mut first: bool = true;
         let mut v = vec![];
@@ -1031,14 +1029,14 @@ impl<'a> Parser<'a> {
                 if first {
                     first = false;
                 } else {
-                    if let Err(e) = self.expect(t) {
-                        fe(e);
+                    if let Err(mut e) = self.expect(t) {
                         // Attempt to keep parsing if it was a similar separator
                         if let Some(ref tokens) = t.similar_tokens() {
                             if tokens.contains(&self.token) {
                                 self.bump();
                             }
                         }
+                        e.emit();
                         // Attempt to keep parsing if it was an omitted separator
                         match f(self) {
                             Ok(t) => {
@@ -1062,16 +1060,11 @@ impl<'a> Parser<'a> {
                 break;
             }
 
-            match f(self) {
-                Ok(t) => v.push(t),
-                Err(e) => {
-                    fe(e);
-                    break;
-                }
-            }
+            let t = f(self)?;
+            v.push(t);
         }
 
-        v
+        Ok(v)
     }
 
     /// Parse a sequence, including the closing delimiter. The function
@@ -1086,7 +1079,7 @@ impl<'a> Parser<'a> {
         F: FnMut(&mut Parser<'a>) -> PResult<'a,  T>,
     {
         self.expect(bra)?;
-        let result = self.parse_seq_to_before_end(ket, sep, f);
+        let result = self.parse_seq_to_before_end(ket, sep, f)?;
         if self.token == *ket {
             self.bump();
         }
@@ -1105,7 +1098,7 @@ impl<'a> Parser<'a> {
     {
         let lo = self.span;
         self.expect(bra)?;
-        let result = self.parse_seq_to_before_end(ket, sep, f);
+        let result = self.parse_seq_to_before_end(ket, sep, f)?;
         let hi = self.span;
         self.bump();
         Ok(respan(lo.to(hi), result))
@@ -1551,7 +1544,7 @@ impl<'a> Parser<'a> {
         };
 
         let span = lo.to(self.prev_span);
-        let ty = Ty { node: node, span: span, id: ast::DUMMY_NODE_ID };
+        let ty = Ty { node, span, id: ast::DUMMY_NODE_ID };
 
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
@@ -1868,8 +1861,11 @@ impl<'a> Parser<'a> {
         self.parse_path(style)
     }
 
-    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle,
-                           enable_warning: bool) -> PResult<'a, ()> {
+    fn parse_path_segments(&mut self,
+                           segments: &mut Vec<PathSegment>,
+                           style: PathStyle,
+                           enable_warning: bool)
+                           -> PResult<'a, ()> {
         loop {
             segments.push(self.parse_path_segment(style, enable_warning)?);
 
@@ -1914,9 +1910,12 @@ impl<'a> Parser<'a> {
             } else {
                 // `(T, U) -> R`
                 self.bump(); // `(`
-                let inputs = self.parse_seq_to_end(&token::CloseDelim(token::Paren),
-                                                   SeqSep::trailing_allowed(token::Comma),
-                                                   |p| p.parse_ty())?;
+                let inputs = self.parse_seq_to_before_tokens(
+                    &[&token::CloseDelim(token::Paren)],
+                    SeqSep::trailing_allowed(token::Comma),
+                    TokenExpectType::Expect,
+                    |p| p.parse_ty())?;
+                self.bump(); // `)`
                 let output = if self.eat(&token::RArrow) {
                     Some(self.parse_ty_no_plus()?)
                 } else {
@@ -3154,7 +3153,13 @@ impl<'a> Parser<'a> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
         let pat = self.parse_pat()?;
-        self.expect_keyword(keywords::In)?;
+        if !self.eat_keyword(keywords::In) {
+            let in_span = self.prev_span.between(self.span);
+            let mut err = self.sess.span_diagnostic
+                .struct_span_err(in_span, "missing `in` in `for` loop");
+            err.span_suggestion_short(in_span, "try adding `in` here", " in ".into());
+            err.emit();
+        }
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
         let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
@@ -3309,10 +3314,12 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse the RHS of a local variable declaration (e.g. '= 14;')
-    fn parse_initializer(&mut self) -> PResult<'a, Option<P<Expr>>> {
+    fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> {
         if self.check(&token::Eq) {
             self.bump();
             Ok(Some(self.parse_expr()?))
+        } else if skip_eq {
+            Ok(Some(self.parse_expr()?))
         } else {
             Ok(None)
         }
@@ -3719,12 +3726,56 @@ impl<'a> Parser<'a> {
         let lo = self.prev_span;
         let pat = self.parse_pat()?;
 
-        let ty = if self.eat(&token::Colon) {
-            Some(self.parse_ty()?)
+        let (err, ty) = if self.eat(&token::Colon) {
+            // Save the state of the parser before parsing type normally, in case there is a `:`
+            // instead of an `=` typo.
+            let parser_snapshot_before_type = self.clone();
+            let colon_sp = self.prev_span;
+            match self.parse_ty() {
+                Ok(ty) => (None, Some(ty)),
+                Err(mut err) => {
+                    // Rewind to before attempting to parse the type and continue parsing
+                    let parser_snapshot_after_type = self.clone();
+                    mem::replace(self, parser_snapshot_before_type);
+
+                    let snippet = self.sess.codemap().span_to_snippet(pat.span).unwrap();
+                    err.span_label(pat.span, format!("while parsing the type for `{}`", snippet));
+                    (Some((parser_snapshot_after_type, colon_sp, err)), None)
+                }
+            }
         } else {
-            None
+            (None, None)
+        };
+        let init = match (self.parse_initializer(err.is_some()), err) {
+            (Ok(init), None) => {  // init parsed, ty parsed
+                init
+            }
+            (Ok(init), Some((_, colon_sp, mut err))) => {  // init parsed, ty error
+                // Could parse the type as if it were the initializer, it is likely there was a
+                // typo in the code: `:` instead of `=`. Add suggestion and emit the error.
+                err.span_suggestion_short(colon_sp,
+                                          "use `=` if you meant to assign",
+                                          "=".to_string());
+                err.emit();
+                // As this was parsed successfuly, continue as if the code has been fixed for the
+                // rest of the file. It will still fail due to the emitted error, but we avoid
+                // extra noise.
+                init
+            }
+            (Err(mut init_err), Some((snapshot, _, ty_err))) => {  // init error, ty error
+                init_err.cancel();
+                // Couldn't parse the type nor the initializer, only raise the type error and
+                // return to the parser state before parsing the type as the initializer.
+                // let x: <parse_error>;
+                mem::replace(self, snapshot);
+                return Err(ty_err);
+            }
+            (Err(err), None) => {  // init error, ty parsed
+                // Couldn't parse the initializer and we're not attempting to recover a failed
+                // parse of the type, return the error.
+                return Err(err);
+            }
         };
-        let init = self.parse_initializer()?;
         let hi = if self.token == token::Semi {
             self.span
         } else {
@@ -3873,6 +3924,16 @@ impl<'a> Parser<'a> {
         self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
+    fn eat_auto_trait(&mut self) -> bool {
+        if self.token.is_keyword(keywords::Auto)
+            && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
+        {
+            self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
+        } else {
+            false
+        }
+    }
+
     fn is_defaultness(&self) -> bool {
         // `pub` is included for better error messages
         self.token.is_keyword(keywords::Default) &&
@@ -4781,14 +4842,14 @@ impl<'a> Parser<'a> {
             } else if self.eat(&token::Comma) {
                 let mut fn_inputs = vec![self_arg];
                 fn_inputs.append(&mut self.parse_seq_to_before_end(
-                    &token::CloseDelim(token::Paren), sep, parse_arg_fn)
+                    &token::CloseDelim(token::Paren), sep, parse_arg_fn)?
                 );
                 fn_inputs
             } else {
                 return self.unexpected();
             }
         } else {
-            self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
+            self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)?
         };
 
         // Parse closing paren and return type.
@@ -4811,9 +4872,8 @@ impl<'a> Parser<'a> {
                     &[&token::BinOp(token::Or), &token::OrOr],
                     SeqSep::trailing_allowed(token::Comma),
                     TokenExpectType::NoExpect,
-                    |p| p.parse_fn_block_arg(),
-                    |mut e| e.emit()
-                );
+                    |p| p.parse_fn_block_arg()
+                )?;
                 self.expect_or()?;
                 args
             }
@@ -5051,7 +5111,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse trait Foo { ... }
-    fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
         let ident = self.parse_ident()?;
         let mut tps = self.parse_generics()?;
 
@@ -5078,7 +5138,7 @@ impl<'a> Parser<'a> {
                 }
             }
         }
-        Ok((ident, ItemKind::Trait(unsafety, tps, bounds, trait_items), None))
+        Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
     }
 
     /// Parses items implementations variants
@@ -5133,19 +5193,19 @@ impl<'a> Parser<'a> {
 
         if opt_trait.is_some() && self.eat(&token::DotDot) {
             if generics.is_parameterized() {
-                self.span_err(impl_span, "default trait implementations are not \
+                self.span_err(impl_span, "auto trait implementations are not \
                                           allowed to have generics");
             }
 
             if let ast::Defaultness::Default = defaultness {
                 self.span_err(impl_span, "`default impl` is not allowed for \
-                                         default trait implementations");
+                                         auto trait implementations");
             }
 
             self.expect(&token::OpenDelim(token::Brace))?;
             self.expect(&token::CloseDelim(token::Brace))?;
             Ok((keywords::Invalid.ident(),
-             ItemKind::DefaultImpl(unsafety, opt_trait.unwrap()), None))
+             ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None))
         } else {
             if opt_trait.is_some() {
                 ty = self.parse_ty()?;
@@ -5988,13 +6048,19 @@ impl<'a> Parser<'a> {
             return Ok(Some(item));
         }
         if self.check_keyword(keywords::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
+            (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
+            self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
         {
             // UNSAFE TRAIT ITEM
             self.expect_keyword(keywords::Unsafe)?;
-            self.expect_keyword(keywords::Trait)?;
+            let is_auto = if self.eat_keyword(keywords::Trait) {
+                IsAuto::No
+            } else {
+                self.eat_auto_trait();
+                IsAuto::Yes
+            };
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(ast::Unsafety::Unsafe)?;
+                self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
@@ -6097,10 +6163,19 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Trait) {
+        if self.check_keyword(keywords::Trait)
+            || (self.check_keyword(keywords::Auto)
+                && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+        {
+            let is_auto = if self.eat_keyword(keywords::Trait) {
+                IsAuto::No
+            } else {
+                self.eat_auto_trait();
+                IsAuto::Yes
+            };
             // TRAIT ITEM
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(ast::Unsafety::Normal)?;
+                self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8a970fd4098..5cb8e8694cf 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1287,7 +1287,7 @@ impl<'a> State<'a> {
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.ident, item.span, true)?;
             }
-            ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
@@ -1338,10 +1338,11 @@ impl<'a> State<'a> {
                 }
                 self.bclose(item.span)?;
             }
-            ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => {
+            ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
+                self.print_is_auto(is_auto)?;
                 self.word_nbsp("trait")?;
                 self.print_ident(item.ident)?;
                 self.print_generics(generics)?;
@@ -1986,6 +1987,15 @@ impl<'a> State<'a> {
             Fixity::None => (prec + 1, prec + 1),
         };
 
+        let left_prec = match (&lhs.node, op.node) {
+            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
+            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
+            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
+            (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt) |
+            (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
+            _ => left_prec,
+        };
+
         self.print_expr_maybe_paren(lhs, left_prec)?;
         self.s.space()?;
         self.word_space(op.node.to_string())?;
@@ -3123,6 +3133,13 @@ impl<'a> State<'a> {
             ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
         }
     }
+
+    pub fn print_is_auto(&mut self, s: ast::IsAuto) -> io::Result<()> {
+        match s {
+            ast::IsAuto::Yes => self.word_nbsp("auto"),
+            ast::IsAuto::No => Ok(()),
+        }
+    }
 }
 
 fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 96e47a6cc0f..c2e90f0bb13 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -281,7 +281,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(type_parameters);
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemKind::DefaultImpl(_, ref trait_ref) => {
+        ItemKind::AutoImpl(_, ref trait_ref) => {
             visitor.visit_trait_ref(trait_ref)
         }
         ItemKind::Impl(_, _, _,
@@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_variant_data(struct_definition, item.ident,
                                      generics, item.id, item.span);
         }
-        ItemKind::Trait(_, ref generics, ref bounds, ref methods) => {
+        ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_trait_item, methods);
diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml
index dd8129bab51..aad2155157d 100644
--- a/src/libsyntax_pos/Cargo.toml
+++ b/src/libsyntax_pos/Cargo.toml
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
 [dependencies]
 serialize = { path = "../libserialize" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+unicode-width = "0.1.4"
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 44e73d876e8..47755dc1d54 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -44,6 +44,8 @@ use serialize::{Encodable, Decodable, Encoder, Decoder};
 extern crate serialize;
 extern crate serialize as rustc_serialize; // used by deriving
 
+extern crate unicode_width;
+
 pub mod hygiene;
 pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
 
@@ -494,6 +496,63 @@ pub struct MultiByteChar {
     pub bytes: usize,
 }
 
+/// Identifies an offset of a non-narrow character in a FileMap
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq)]
+pub enum NonNarrowChar {
+    /// Represents a zero-width character
+    ZeroWidth(BytePos),
+    /// Represents a wide (fullwidth) character
+    Wide(BytePos),
+}
+
+impl NonNarrowChar {
+    fn new(pos: BytePos, width: usize) -> Self {
+        match width {
+            0 => NonNarrowChar::ZeroWidth(pos),
+            2 => NonNarrowChar::Wide(pos),
+            _ => panic!("width {} given for non-narrow character", width),
+        }
+    }
+
+    /// Returns the absolute offset of the character in the CodeMap
+    pub fn pos(&self) -> BytePos {
+        match *self {
+            NonNarrowChar::ZeroWidth(p) |
+            NonNarrowChar::Wide(p) => p,
+        }
+    }
+
+    /// Returns the width of the character, 0 (zero-width) or 2 (wide)
+    pub fn width(&self) -> usize {
+        match *self {
+            NonNarrowChar::ZeroWidth(_) => 0,
+            NonNarrowChar::Wide(_) => 2,
+        }
+    }
+}
+
+impl Add<BytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn add(self, rhs: BytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
+        }
+    }
+}
+
+impl Sub<BytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn sub(self, rhs: BytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
+        }
+    }
+}
+
 /// The state of the lazy external source loading mechanism of a FileMap.
 #[derive(PartialEq, Eq, Clone)]
 pub enum ExternalSource {
@@ -552,11 +611,13 @@ pub struct FileMap {
     pub lines: RefCell<Vec<BytePos>>,
     /// Locations of multi-byte characters in the source code
     pub multibyte_chars: RefCell<Vec<MultiByteChar>>,
+    /// Width of characters that are not narrow in the source code
+    pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
 }
 
 impl Encodable for FileMap {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("FileMap", 7, |s| {
+        s.emit_struct("FileMap", 8, |s| {
             s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
             s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
             s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?;
@@ -610,6 +671,9 @@ impl Encodable for FileMap {
             })?;
             s.emit_struct_field("multibyte_chars", 5, |s| {
                 (*self.multibyte_chars.borrow()).encode(s)
+            })?;
+            s.emit_struct_field("non_narrow_chars", 7, |s| {
+                (*self.non_narrow_chars.borrow()).encode(s)
             })
         })
     }
@@ -618,7 +682,7 @@ impl Encodable for FileMap {
 impl Decodable for FileMap {
     fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
 
-        d.read_struct("FileMap", 6, |d| {
+        d.read_struct("FileMap", 8, |d| {
             let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
             let name_was_remapped: bool =
                 d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?;
@@ -657,6 +721,8 @@ impl Decodable for FileMap {
             })?;
             let multibyte_chars: Vec<MultiByteChar> =
                 d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
+            let non_narrow_chars: Vec<NonNarrowChar> =
+                d.read_struct_field("non_narrow_chars", 7, |d| Decodable::decode(d))?;
             Ok(FileMap {
                 name,
                 name_was_remapped,
@@ -671,7 +737,8 @@ impl Decodable for FileMap {
                 src_hash,
                 external_src: RefCell::new(ExternalSource::AbsentOk),
                 lines: RefCell::new(lines),
-                multibyte_chars: RefCell::new(multibyte_chars)
+                multibyte_chars: RefCell::new(multibyte_chars),
+                non_narrow_chars: RefCell::new(non_narrow_chars)
             })
         })
     }
@@ -709,6 +776,7 @@ impl FileMap {
             end_pos: Pos::from_usize(end_pos),
             lines: RefCell::new(Vec::new()),
             multibyte_chars: RefCell::new(Vec::new()),
+            non_narrow_chars: RefCell::new(Vec::new()),
         }
     }
 
@@ -798,6 +866,23 @@ impl FileMap {
         self.multibyte_chars.borrow_mut().push(mbc);
     }
 
+    pub fn record_width(&self, pos: BytePos, ch: char) {
+        let width = match ch {
+            '\t' | '\n' =>
+                // Tabs will consume one column.
+                // Make newlines take one column so that displayed spans can point them.
+                1,
+            ch =>
+                // Assume control characters are zero width.
+                // FIXME: How can we decide between `width` and `width_cjk`?
+                unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0),
+        };
+        // Only record non-narrow characters.
+        if width != 1 {
+            self.non_narrow_chars.borrow_mut().push(NonNarrowChar::new(pos, width));
+        }
+    }
+
     pub fn is_real_file(&self) -> bool {
         !(self.name.starts_with("<") &&
           self.name.ends_with(">"))
@@ -944,7 +1029,9 @@ pub struct Loc {
     /// The (1-based) line number
     pub line: usize,
     /// The (0-based) column offset
-    pub col: CharPos
+    pub col: CharPos,
+    /// The (0-based) column offset when displayed
+    pub col_display: usize,
 }
 
 /// A source code location used as the result of lookup_char_pos_adj
diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs
index c2b32171a9a..b23e40ce7a9 100644
--- a/src/libsyntax_pos/span_encoding.rs
+++ b/src/libsyntax_pos/span_encoding.rs
@@ -59,9 +59,11 @@ const LEN_INDEX: usize = 1;
 const CTXT_INDEX: usize = 2;
 
 // Tag = 0, inline format.
-// -----------------------------------
-// | base 31:8  | len 7:1  | tag 0:0 |
-// -----------------------------------
+// -------------------------------------------------------------
+// | base 31:8  | len 7:1  | ctxt (currently 0 bits) | tag 0:0 |
+// -------------------------------------------------------------
+// Since there are zero bits for ctxt, only SpanData with a 0 SyntaxContext
+// can be inline.
 const INLINE_SIZES: [u32; 3] = [24, 7, 0];
 const INLINE_OFFSETS: [u32; 3] = [8, 1, 1];
 
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 872fc031cfb..26e6f27e20f 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -309,11 +309,12 @@ declare_keywords! {
     (54, Yield,          "yield")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (55, Catch,          "catch")
-    (56, Default,        "default")
-    (57, Dyn,            "dyn")
-    (58, StaticLifetime, "'static")
-    (59, Union,          "union")
+    (55, Auto,           "auto")
+    (56, Catch,          "catch")
+    (57, Default,        "default")
+    (58, Dyn,            "dyn")
+    (59, StaticLifetime, "'static")
+    (60, Union,          "union")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index 8733c7436d5..d33b5248629 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -14,7 +14,7 @@
 // When an executable or dylib image is linked, all user code and libraries are
 // "sandwiched" between these two object files, so code or data from rsbegin.o
 // become first in the respective sections of the image, whereas code and data
-// from rsend.o become the last ones.  This effect can be used to place symbols
+// from rsend.o become the last ones. This effect can be used to place symbols
 // at the beginning or at the end of a section, as well as to insert any required
 // headers or footers.
 //
@@ -31,11 +31,15 @@
 trait Sized {}
 #[lang = "sync"]
 trait Sync {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Sync for .. {}
 #[lang = "copy"]
 trait Copy {}
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang = "drop_in_place"]
diff --git a/src/rtstartup/rsend.rs b/src/rtstartup/rsend.rs
index a6aed3540dd..410366d0d7f 100644
--- a/src/rtstartup/rsend.rs
+++ b/src/rtstartup/rsend.rs
@@ -23,6 +23,8 @@ impl<T> Sync for T {}
 trait Copy {}
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang = "drop_in_place"]
diff --git a/src/test/codegen-units/item-collection/unreferenced-const-fn.rs b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs
new file mode 100644
index 00000000000..59b25d8beca
--- /dev/null
+++ b/src/test/codegen-units/item-collection/unreferenced-const-fn.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=lazy
+
+// NB: We do not expect *any* translation item to be generated here.
+
+#![feature(const_fn)]
+#![deny(dead_code)]
+#![crate_type = "rlib"]
+
+pub const fn foo(x: u32) -> u32 {
+    x + 0xf00
+}
diff --git a/src/test/codegen-units/item-collection/unreferenced-inline-function.rs b/src/test/codegen-units/item-collection/unreferenced-inline-function.rs
new file mode 100644
index 00000000000..75d41a38012
--- /dev/null
+++ b/src/test/codegen-units/item-collection/unreferenced-inline-function.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=lazy
+
+// NB: We do not expect *any* translation item to be generated here.
+
+#![deny(dead_code)]
+#![crate_type = "rlib"]
+
+#[inline]
+pub fn foo() -> bool {
+    [1, 2] == [3, 4]
+}
+
diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs
index 29528644ed0..da96c5e183d 100644
--- a/src/test/codegen-units/partitioning/extern-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs
@@ -16,7 +16,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
@@ -25,20 +25,20 @@ extern crate cgu_extern_drop_glue;
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
-//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[Internal]
-fn user()
+//~ TRANS_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
+pub fn user()
 {
     //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
-mod mod1 {
+pub mod mod1 {
     use cgu_extern_drop_glue;
 
     struct LocalStruct(cgu_extern_drop_glue::Struct);
 
-    //~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[Internal]
-    fn user()
+    //~ TRANS_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
+    pub fn user()
     {
         //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
diff --git a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs
index 4bfd35b59bc..01600c03ba2 100644
--- a/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs
+++ b/src/test/codegen-units/partitioning/inlining-from-extern-crate.rs
@@ -35,10 +35,10 @@ pub fn user()
     cgu_explicit_inlining::never_inlined();
 }
 
-mod mod1 {
+pub mod mod1 {
     use cgu_explicit_inlining;
 
-    //~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[Internal]
+    //~ TRANS_ITEM fn inlining_from_extern_crate::mod1[0]::user[0] @@ inlining_from_extern_crate-mod1[External]
     pub fn user()
     {
         cgu_explicit_inlining::inlined();
@@ -48,10 +48,10 @@ mod mod1 {
     }
 }
 
-mod mod2 {
+pub mod mod2 {
     use cgu_explicit_inlining;
 
-    //~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[Internal]
+    //~ TRANS_ITEM fn inlining_from_extern_crate::mod2[0]::user[0] @@ inlining_from_extern_crate-mod2[External]
     pub fn user()
     {
         cgu_explicit_inlining::always_inlined();
diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs
index 65e91343ccf..f7c05285ed6 100644
--- a/src/test/codegen-units/partitioning/local-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/local-drop-glue.rs
@@ -15,7 +15,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 //~ TRANS_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
@@ -32,8 +32,8 @@ struct Outer {
     _a: Struct
 }
 
-//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[Internal]
-fn user()
+//~ TRANS_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[External]
+pub fn user()
 {
     let _ = Outer {
         _a: Struct {
@@ -42,7 +42,7 @@ fn user()
     };
 }
 
-mod mod1
+pub mod mod1
 {
     use super::Struct;
 
@@ -53,8 +53,8 @@ mod mod1
         _b: (u32, Struct),
     }
 
-    //~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[Internal]
-    fn user()
+    //~ TRANS_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[External]
+    pub fn user()
     {
         let _ = Struct2 {
             _a: Struct { _a: 0 },
diff --git a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs
index 84464a627be..cf197301eec 100644
--- a/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs
+++ b/src/test/codegen-units/partitioning/local-inlining-but-not-all.rs
@@ -27,28 +27,28 @@ mod inline {
     }
 }
 
-mod user1 {
+pub mod user1 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::user1[0]::foo[0] @@ local_inlining_but_not_all-user1[Internal]
-    fn foo() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::user1[0]::foo[0] @@ local_inlining_but_not_all-user1[External]
+    pub fn foo() {
         inline::inlined_function();
     }
 }
 
-mod user2 {
+pub mod user2 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::user2[0]::bar[0] @@ local_inlining_but_not_all-user2[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::user2[0]::bar[0] @@ local_inlining_but_not_all-user2[External]
+    pub fn bar() {
         inline::inlined_function();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_inlining_but_not_all::non_user[0]::baz[0] @@ local_inlining_but_not_all-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_inlining_but_not_all::non_user[0]::baz[0] @@ local_inlining_but_not_all-non_user[External]
+    pub fn baz() {
 
     }
 }
diff --git a/src/test/codegen-units/partitioning/local-inlining.rs b/src/test/codegen-units/partitioning/local-inlining.rs
index f3176191241..3502aa59fdc 100644
--- a/src/test/codegen-units/partitioning/local-inlining.rs
+++ b/src/test/codegen-units/partitioning/local-inlining.rs
@@ -28,28 +28,28 @@ mod inline {
     }
 }
 
-mod user1 {
+pub mod user1 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[Internal]
-    fn foo() {
+    //~ TRANS_ITEM fn local_inlining::user1[0]::foo[0] @@ local_inlining-user1[External]
+    pub fn foo() {
         inline::inlined_function();
     }
 }
 
-mod user2 {
+pub mod user2 {
     use super::inline;
 
-    //~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_inlining::user2[0]::bar[0] @@ local_inlining-user2[External]
+    pub fn bar() {
         inline::inlined_function();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_inlining::non_user[0]::baz[0] @@ local_inlining-non_user[External]
+    pub fn baz() {
 
     }
 }
diff --git a/src/test/codegen-units/partitioning/local-transitive-inlining.rs b/src/test/codegen-units/partitioning/local-transitive-inlining.rs
index bda76a8789f..ed883954f3f 100644
--- a/src/test/codegen-units/partitioning/local-transitive-inlining.rs
+++ b/src/test/codegen-units/partitioning/local-transitive-inlining.rs
@@ -15,7 +15,7 @@
 // compile-flags:-Zinline-in-all-cgus
 
 #![allow(dead_code)]
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 mod inline {
 
@@ -37,19 +37,19 @@ mod direct_user {
     }
 }
 
-mod indirect_user {
+pub mod indirect_user {
     use super::direct_user;
 
-    //~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[Internal]
-    fn bar() {
+    //~ TRANS_ITEM fn local_transitive_inlining::indirect_user[0]::bar[0] @@ local_transitive_inlining-indirect_user[External]
+    pub fn bar() {
         direct_user::foo();
     }
 }
 
-mod non_user {
+pub mod non_user {
 
-    //~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[Internal]
-    fn baz() {
+    //~ TRANS_ITEM fn local_transitive_inlining::non_user[0]::baz[0] @@ local_transitive_inlining-non_user[External]
+    pub fn baz() {
 
     }
 }
diff --git a/src/test/codegen-units/partitioning/statics.rs b/src/test/codegen-units/partitioning/statics.rs
index 8cbce12b52c..12ef34441ff 100644
--- a/src/test/codegen-units/partitioning/statics.rs
+++ b/src/test/codegen-units/partitioning/statics.rs
@@ -13,7 +13,7 @@
 // incremental compilation
 // compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/statics
 
-#![crate_type="lib"]
+#![crate_type="rlib"]
 
 //~ TRANS_ITEM static statics::FOO[0] @@ statics[Internal]
 static FOO: u32 = 0;
@@ -21,8 +21,8 @@ static FOO: u32 = 0;
 //~ TRANS_ITEM static statics::BAR[0] @@ statics[Internal]
 static BAR: u32 = 0;
 
-//~ TRANS_ITEM fn statics::function[0] @@ statics[Internal]
-fn function() {
+//~ TRANS_ITEM fn statics::function[0] @@ statics[External]
+pub fn function() {
     //~ TRANS_ITEM static statics::function[0]::FOO[0] @@ statics[Internal]
     static FOO: u32 = 0;
 
@@ -30,15 +30,15 @@ fn function() {
     static BAR: u32 = 0;
 }
 
-mod mod1 {
+pub mod mod1 {
     //~ TRANS_ITEM static statics::mod1[0]::FOO[0] @@ statics-mod1[Internal]
     static FOO: u32 = 0;
 
     //~ TRANS_ITEM static statics::mod1[0]::BAR[0] @@ statics-mod1[Internal]
     static BAR: u32 = 0;
 
-    //~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[Internal]
-    fn function() {
+    //~ TRANS_ITEM fn statics::mod1[0]::function[0] @@ statics-mod1[External]
+    pub fn function() {
         //~ TRANS_ITEM static statics::mod1[0]::function[0]::FOO[0] @@ statics-mod1[Internal]
         static FOO: u32 = 0;
 
diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs
index bd85e303143..342a4f0d085 100644
--- a/src/test/codegen/adjustments.rs
+++ b/src/test/codegen/adjustments.rs
@@ -15,7 +15,7 @@
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK-LABEL: @no_op_slice_adjustment
diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs
index cc13d4a7b68..346c5da8d1b 100644
--- a/src/test/codegen/fastcall-inreg.rs
+++ b/src/test/codegen/fastcall-inreg.rs
@@ -59,28 +59,28 @@
 
 #![crate_type = "lib"]
 
-mod tests {
+pub mod tests {
     // CHECK: @f1(i32 inreg %arg0, i32 inreg %arg1, i32 %arg2)
     #[no_mangle]
-    extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
 
     // CHECK: @f2(i32* inreg %arg0, i32* inreg %arg1, i32* %arg2)
     #[no_mangle]
-    extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
+    pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
 
     // CHECK: @f3(float %arg0, i32 inreg %arg1, i32 inreg %arg2, i32 %arg3)
     #[no_mangle]
-    extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
 
     // CHECK: @f4(i32 inreg %arg0, float %arg1, i32 inreg %arg2, i32 %arg3)
     #[no_mangle]
-    extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
+    pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
 
     // CHECK: @f5(i64 %arg0, i32 %arg1)
     #[no_mangle]
-    extern "fastcall" fn f5(_: i64, _: i32) {}
+    pub extern "fastcall" fn f5(_: i64, _: i32) {}
 
     // CHECK: @f6(i1 inreg zeroext %arg0, i32 inreg %arg1, i32 %arg2)
     #[no_mangle]
-    extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
+    pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
 }
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index d4c7fe9e80a..29e2840c881 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -93,20 +93,20 @@ pub fn struct_return() -> S {
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK: @slice(i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn slice(_: &[u8]) {
+pub fn slice(_: &[u8]) {
 }
 
 // CHECK: @mutable_slice(i8* nonnull %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 // ... there's this LLVM bug that forces us to not use noalias, see #29485
 #[no_mangle]
-fn mutable_slice(_: &mut [u8]) {
+pub fn mutable_slice(_: &mut [u8]) {
 }
 
 // CHECK: @unsafe_slice(%UnsafeInner* nonnull %arg0.ptr, [[USIZE]] %arg0.meta)
@@ -118,23 +118,23 @@ pub fn unsafe_slice(_: &[UnsafeInner]) {
 // CHECK: @str(i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn str(_: &[u8]) {
+pub fn str(_: &[u8]) {
 }
 
 // CHECK: @trait_borrow({}* nonnull, {}* noalias nonnull readonly)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
-fn trait_borrow(_: &Drop) {
+pub fn trait_borrow(_: &Drop) {
 }
 
 // CHECK: @trait_box({}* noalias nonnull, {}* noalias nonnull readonly)
 #[no_mangle]
-fn trait_box(_: Box<Drop>) {
+pub fn trait_box(_: Box<Drop>) {
 }
 
 // CHECK: { i16*, [[USIZE]] } @return_slice(i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta)
 #[no_mangle]
-fn return_slice(x: &[u16]) -> &[u16] {
+pub fn return_slice(x: &[u16]) -> &[u16] {
   x
 }
 
diff --git a/src/test/codegen/mir_zst_stores.rs b/src/test/codegen/mir_zst_stores.rs
index 36602196cef..884cf59c1c1 100644
--- a/src/test/codegen/mir_zst_stores.rs
+++ b/src/test/codegen/mir_zst_stores.rs
@@ -19,7 +19,7 @@ struct Zst { phantom: PhantomData<Zst> }
 // CHECK-LABEL: @mir
 // CHECK-NOT: store{{.*}}undef
 #[no_mangle]
-fn mir() {
+pub fn mir() {
     let x = Zst { phantom: PhantomData };
     let y = (x, 0);
     drop(y);
diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs
index 9883ca6b35d..aab5f1bfb4f 100644
--- a/src/test/codegen/naked-functions.rs
+++ b/src/test/codegen/naked-functions.rs
@@ -16,10 +16,10 @@
 #![feature(naked_functions)]
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal void @naked_empty()
+// CHECK-NEXT: define void @naked_empty()
 #[no_mangle]
 #[naked]
-fn naked_empty() {
+pub fn naked_empty() {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: ret void
 }
@@ -27,8 +27,8 @@ fn naked_empty() {
 // CHECK: Function Attrs: naked uwtable
 #[no_mangle]
 #[naked]
-// CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}})
-fn naked_with_args(a: isize) {
+// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+}})
+pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
@@ -36,20 +36,20 @@ fn naked_with_args(a: isize) {
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_return()
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_return()
 #[no_mangle]
 #[naked]
-fn naked_with_return() -> isize {
+pub fn naked_with_return() -> isize {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: ret i{{[0-9]+}} 0
     0
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
+// CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
 #[no_mangle]
 #[naked]
-fn naked_with_args_and_return(a: isize) -> isize {
+pub fn naked_with_args_and_return(a: isize) -> isize {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
@@ -58,10 +58,10 @@ fn naked_with_args_and_return(a: isize) -> isize {
 }
 
 // CHECK: Function Attrs: naked uwtable
-// CHECK-NEXT: define internal void @naked_recursive()
+// CHECK-NEXT: define void @naked_recursive()
 #[no_mangle]
 #[naked]
-fn naked_recursive() {
+pub fn naked_recursive() {
     // CHECK-NEXT: {{.+}}:
     // CHECK-NEXT: call void @naked_empty()
 
diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs
index fd1a14020d8..4b713e28b05 100644
--- a/src/test/codegen/refs.rs
+++ b/src/test/codegen/refs.rs
@@ -15,7 +15,7 @@
 // Hack to get the correct size for the length part in slices
 // CHECK: @helper([[USIZE:i[0-9]+]] %arg0)
 #[no_mangle]
-fn helper(_: usize) {
+pub fn helper(_: usize) {
 }
 
 // CHECK-LABEL: @ref_dst
diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs
new file mode 100644
index 00000000000..64ab19cceee
--- /dev/null
+++ b/src/test/codegen/unchecked-float-casts.rs
@@ -0,0 +1,65 @@
+// 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.
+
+// compile-flags: -C no-prepopulate-passes
+
+// This file tests that we don't generate any code for saturation if
+// -Z saturating-float-casts is not enabled.
+
+#![crate_type = "lib"]
+#![feature(i128_type)]
+
+// CHECK-LABEL: @f32_to_u32
+#[no_mangle]
+pub fn f32_to_u32(x: f32) -> u32 {
+    // CHECK: fptoui
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as u32
+}
+
+// CHECK-LABEL: @f32_to_i32
+#[no_mangle]
+pub fn f32_to_i32(x: f32) -> i32 {
+    // CHECK: fptosi
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as i32
+}
+
+#[no_mangle]
+pub fn f64_to_u8(x: f32) -> u16 {
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as u16
+}
+
+// CHECK-LABEL: @i32_to_f64
+#[no_mangle]
+pub fn i32_to_f64(x: i32) -> f64 {
+    // CHECK: sitofp
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as f64
+}
+
+// CHECK-LABEL: @u128_to_f32
+#[no_mangle]
+pub fn u128_to_f32(x: u128) -> f32 {
+    // CHECK: uitofp
+    // CHECK-NOT: fcmp
+    // CHECK-NOT: icmp
+    // CHECK-NOT: select
+    x as f32
+}
diff --git a/src/test/compile-fail/E0029.rs b/src/test/compile-fail/E0029.rs
index ec84e2a3f8a..e43290bb154 100644
--- a/src/test/compile-fail/E0029.rs
+++ b/src/test/compile-fail/E0029.rs
@@ -17,6 +17,7 @@ fn main() {
         //~| NOTE ranges require char or numeric types
         //~| NOTE start type: &'static str
         //~| NOTE end type: &'static str
+        //~| ERROR non-reference pattern used to match a reference
         _ => {}
     }
 }
diff --git a/src/test/compile-fail/E0534.rs b/src/test/compile-fail/E0534.rs
index 8c036e6076d..fc465b26869 100644
--- a/src/test/compile-fail/E0534.rs
+++ b/src/test/compile-fail/E0534.rs
@@ -11,4 +11,6 @@
 #[inline()] //~ ERROR E0534
 pub fn something() {}
 
-fn main() {}
+fn main() {
+    something();
+}
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/auto-impl-future-compat.rs
new file mode 100644
index 00000000000..5c32a756398
--- /dev/null
+++ b/src/test/compile-fail/auto-impl-future-compat.rs
@@ -0,0 +1,16 @@
+// 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(optin_builtin_traits)]
+
+trait Foo {}
+impl Foo for .. {}
+//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
+//~^^ WARN this was previously accepted by the compiler
diff --git a/src/test/compile-fail/auto-trait-validation.rs b/src/test/compile-fail/auto-trait-validation.rs
new file mode 100644
index 00000000000..b28b776d9c2
--- /dev/null
+++ b/src/test/compile-fail/auto-trait-validation.rs
@@ -0,0 +1,22 @@
+// 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(optin_builtin_traits)]
+
+auto trait Generic<T> {}
+//~^ ERROR auto traits cannot have generics
+//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
+auto trait Bound : Copy {}
+//~^ ERROR auto traits cannot have super traits
+//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
+auto trait MyTrait { fn foo() {} }
+//~^ ERROR auto traits cannot contain items
+//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
+fn main() {}
diff --git a/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs b/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
index 2e425ac96c5..1e1c55de87e 100644
--- a/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
+++ b/src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
@@ -12,6 +12,7 @@
 #![crate_type = "rlib"]
 
 pub trait DefaultedTrait { }
+#[allow(auto_impl)]
 impl DefaultedTrait for .. { }
 
 pub struct Something<T> { t: T }
diff --git a/src/test/compile-fail/bad-intrinsic-monomorphization.rs b/src/test/compile-fail/bad-intrinsic-monomorphization.rs
index cfb64f80767..2fe94d43acd 100644
--- a/src/test/compile-fail/bad-intrinsic-monomorphization.rs
+++ b/src/test/compile-fail/bad-intrinsic-monomorphization.rs
@@ -10,6 +10,7 @@
 
 #![feature(repr_simd, platform_intrinsics, core_intrinsics)]
 #![allow(warnings)]
+#![crate_type = "rlib"]
 
 // Bad monomorphizations could previously cause LLVM asserts even though the
 // error was caught in the compiler.
@@ -21,21 +22,19 @@ extern "platform-intrinsic" {
 use std::intrinsics;
 
 #[derive(Copy, Clone)]
-struct Foo(i64);
+pub struct Foo(i64);
 
-unsafe fn test_cttz(v: Foo) -> Foo {
+pub unsafe fn test_cttz(v: Foo) -> Foo {
     intrinsics::cttz(v)
     //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
+pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo {
     intrinsics::fadd_fast(a, b)
     //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo`
 }
 
-unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
+pub unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo {
     simd_add(a, b)
     //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo`
 }
-
-fn main() {}
diff --git a/src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs b/src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
new file mode 100644
index 00000000000..8bab6e8dfce
--- /dev/null
+++ b/src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
@@ -0,0 +1,24 @@
+// Copyright 2012 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: -Z emit-end-regions -Z borrowck-mir
+
+fn foo(_:String) {}
+
+fn main()
+{
+    let my_str = "hello".to_owned();
+    match Some(42) {
+        Some(_) if { drop(my_str); false } => {}
+        Some(_) => {}
+        None => { foo(my_str); } //~ ERROR (Mir) [E0381]
+    }
+}
diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
index 1d21f40fcca..5f236014457 100644
--- a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
+++ b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
@@ -11,6 +11,24 @@
 // revisions: ast mir
 //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
 
+enum Foo {
+    A(i32),
+    B
+}
+
+fn match_enum() {
+    let mut foo = Foo::B;
+    let p = &mut foo;
+    let _ = match foo {
+        Foo::B => 1, //[mir]~ ERROR (Mir) [E0503]
+        _ => 2,
+        Foo::A(x) => x //[ast]~ ERROR [E0503]
+                       //[mir]~^ ERROR (Ast) [E0503]
+                       //[mir]~| ERROR (Mir) [E0503]
+    };
+}
+
+
 fn main() {
     let mut x = 1;
     let _x = &mut x;
diff --git a/src/test/compile-fail/closure-expected-type/README.md b/src/test/compile-fail/closure-expected-type/README.md
new file mode 100644
index 00000000000..9995b00a9a7
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/README.md
@@ -0,0 +1 @@
+See `src/test/run-pass/closure-expected-type`.
diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs
new file mode 100644
index 00000000000..f1b198a0591
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs
@@ -0,0 +1,49 @@
+// 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.
+
+// must-compile-successfully
+
+#![feature(underscore_lifetimes)]
+#![allow(warnings)]
+
+type Different<'a, 'b> = &'a mut (&'a (), &'b ());
+type Same<'a> = Different<'a, 'a>;
+
+fn with_closure_expecting_different<F>(_: F)
+    where F: for<'a, 'b> FnOnce(Different<'a, 'b>)
+{
+}
+
+fn with_closure_expecting_different_anon<F>(_: F)
+    where F: FnOnce(Different<'_, '_>)
+{
+}
+
+fn supplying_nothing_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different| {
+    })
+}
+
+fn supplying_nothing_expecting_named() {
+    with_closure_expecting_different(|x: Different| {
+    })
+}
+
+fn supplying_underscore_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different<'_, '_>| {
+    })
+}
+
+fn supplying_underscore_expecting_named() {
+    with_closure_expecting_different(|x: Different<'_, '_>| {
+    })
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs
new file mode 100644
index 00000000000..645fd1f80ba
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs
@@ -0,0 +1,70 @@
+// 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.
+
+#![feature(underscore_lifetimes)]
+
+fn with_closure_expecting_fn_with_free_region<F>(_: F)
+    where F: for<'a> FnOnce(fn(&'a u32), &i32)
+{
+}
+
+fn with_closure_expecting_fn_with_bound_region<F>(_: F)
+    where F: FnOnce(fn(&u32), &i32)
+{
+}
+
+fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, the type given for `'x` "obscures" a region from the
+    // expected signature that is bound at closure level.
+    with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn expect_free_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, just as is expected, so no error
+    // results.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_free_region(|_x: Foo<'_>, y| {});
+}
+
+fn expect_free_supply_bound() {
+    // Here, we are given a function whose region is bound at closure level,
+    // but we expect one bound in the argument. Error results.
+    with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, we are given a `fn(&u32)` but we expect a `fn(&'x
+    // u32)`. In principle, this could be ok, but we demand equality.
+    with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, but we expect something bound at
+    // the argument level.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_bound<'x>(x: &'x u32) {
+    // No error in this case. The supplied type supplies the bound
+    // regions, and hence we are able to figure out the type of `y`
+    // from the expected type
+    with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {
+    });
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs
new file mode 100644
index 00000000000..bef69a4b0b9
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs
@@ -0,0 +1,35 @@
+// 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.
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, A)
+{
+}
+
+fn a() {
+    with_closure(|x: u32, y| {
+        // We deduce type of `y` from `x`.
+    });
+}
+
+fn b() {
+    // Here we take the supplied types, resulting in an error later on.
+    with_closure(|x: u32, y: i32| {
+        //~^ ERROR type mismatch in closure arguments
+    });
+}
+
+fn c() {
+    with_closure(|x, y: i32| {
+        // We deduce type of `x` from `y`.
+    });
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
new file mode 100644
index 00000000000..f8cb643c8d6
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// must-compile-successfully
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar() {
+    // This version also works.
+    with_closure(|x: &u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
new file mode 100644
index 00000000000..d3c111c5daf
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
@@ -0,0 +1,29 @@
+// 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.
+
+// must-compile-successfully
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar<'x>(x: &'x u32) {
+    // Same.
+    with_closure(|x: &'x u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs b/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
new file mode 100644
index 00000000000..9da12dc901f
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
@@ -0,0 +1,80 @@
+// 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.
+
+#![allow(warnings)]
+
+fn closure_expecting_bound<F>(_: F)
+    where F: FnOnce(&u32)
+{
+}
+
+fn closure_expecting_free<'a, F>(_: F)
+    where F: FnOnce(&'a u32)
+{
+}
+
+fn expect_bound_supply_nothing() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x| {
+        f = Some(x); //~ ERROR E0495
+    });
+}
+
+fn expect_bound_supply_bound() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`, even with an explicit type annotation on
+    // closure:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x: &u32| {
+        f = Some(x); //~ ERROR E0495
+    });
+}
+
+fn expect_bound_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here we give a type annotation that `x` should be free. We get
+    // an error because of that.
+    closure_expecting_bound(|x: &'x u32| {
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
+
+        // And we still cannot let `x` escape into `f`.
+        f = Some(x);
+        //~^ ERROR cannot infer
+    });
+}
+
+fn expect_free_supply_nothing() {
+    let mut f: Option<&u32> = None;
+    closure_expecting_free(|x| f = Some(x)); // OK
+}
+
+fn expect_free_supply_bound() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &u32| f = Some(x)); // OK
+}
+
+fn expect_free_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs b/src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs
new file mode 100644
index 00000000000..377eaadbd6a
--- /dev/null
+++ b/src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs
@@ -0,0 +1,29 @@
+// 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.
+
+fn with_closure<F, A, B>(_: F)
+    where F: FnOnce(A, B)
+{
+}
+
+fn a() {
+    // Type of `y` is unconstrained.
+    with_closure(|x: u32, y| {}); //~ ERROR E0282
+}
+
+fn b() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn c() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs
index e6bf068156c..9c26b8b05f2 100644
--- a/src/test/compile-fail/coherence-default-trait-impl.rs
+++ b/src/test/compile-fail/coherence-default-trait-impl.rs
@@ -12,18 +12,22 @@
 
 trait MyTrait { fn foo() {} }
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
-//~^ ERROR redundant default implementations of trait `MyTrait`
+//~^ ERROR redundant auto implementations of trait `MyTrait`
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 trait MySafeTrait {}
 
+#[allow(auto_impl)]
 unsafe impl MySafeTrait for .. {}
 //~^ ERROR implementing the trait `MySafeTrait` is not unsafe
 
 unsafe trait MyUnsafeTrait {}
 
+#[allow(auto_impl)]
 impl MyUnsafeTrait for .. {}
 //~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
 
diff --git a/src/test/compile-fail/dupe-symbols-2.rs b/src/test/compile-fail/dupe-symbols-2.rs
index 976a65589b8..1f19bd2f249 100644
--- a/src/test/compile-fail/dupe-symbols-2.rs
+++ b/src/test/compile-fail/dupe-symbols-2.rs
@@ -11,13 +11,13 @@
 #![crate_type="rlib"]
 #![allow(warnings)]
 
-mod a {
+pub mod a {
     #[no_mangle]
     pub extern fn fail() {
     }
 }
 
-mod b {
+pub mod b {
     #[no_mangle]
     pub extern fn fail() {
     //~^ symbol `fail` is already defined
diff --git a/src/test/compile-fail/feature-gate-match_default_bindings.rs b/src/test/compile-fail/feature-gate-match_default_bindings.rs
index 2b3bf94eadc..4ee2c1e2936 100644
--- a/src/test/compile-fail/feature-gate-match_default_bindings.rs
+++ b/src/test/compile-fail/feature-gate-match_default_bindings.rs
@@ -10,7 +10,8 @@
 
 pub fn main() {
     match &Some(3) {
-        Some(n) => {}, //~ ERROR mismatched types [E0308]
+        Some(n) => {},
+        //~^ ERROR non-reference pattern used to match a reference
         _ => panic!(),
     }
 }
diff --git a/src/test/compile-fail/feature-gate-non_exhaustive.rs b/src/test/compile-fail/feature-gate-non_exhaustive.rs
new file mode 100644
index 00000000000..d2711084a4d
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-non_exhaustive.rs
@@ -0,0 +1,20 @@
+// Copyright 2015 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(non_exhaustive)]
+
+#[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs b/src/test/compile-fail/feature-gate-optin-builtin-traits.rs
index 59d7473a741..4c5502cec18 100644
--- a/src/test/compile-fail/feature-gate-optin-builtin-traits.rs
+++ b/src/test/compile-fail/feature-gate-optin-builtin-traits.rs
@@ -17,8 +17,12 @@ trait DummyTrait {
     fn dummy(&self) {}
 }
 
+auto trait AutoDummyTrait {}
+//~^ ERROR auto traits are experimental and possibly buggy
+
+#[allow(auto_impl)]
 impl DummyTrait for .. {}
-//~^ ERROR default trait implementations are experimental and possibly buggy
+//~^ ERROR auto trait implementations are experimental and possibly buggy
 
 impl !DummyTrait for DummyStruct {}
 //~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
diff --git a/src/test/compile-fail/float-int-invalid-const-cast.rs b/src/test/compile-fail/float-int-invalid-const-cast.rs
new file mode 100644
index 00000000000..2efefd92691
--- /dev/null
+++ b/src/test/compile-fail/float-int-invalid-const-cast.rs
@@ -0,0 +1,61 @@
+// 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(i128_type)]
+#![allow(const_err)] // this test is only about hard errors
+
+use std::{f32, f64};
+
+// Forces evaluation of constants, triggering hard error
+fn force<T>(_: T) {}
+
+fn main() {
+    { const X: u16 = -1. as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = -100. as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f32::NAN as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = f32::NAN as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u64 = f32::NAN as u64; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f32::NAN as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f32::INFINITY as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = f32::INFINITY as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f32::INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f32::INFINITY as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = f32::NEG_INFINITY as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: u16 = f32::NEG_INFINITY as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: i64 = f32::NEG_INFINITY as i64; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f32::NEG_INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f64::NAN as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = f64::NAN as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u64 = f64::NAN as u64; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f64::NAN as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: i8 = f64::INFINITY as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = f64::INFINITY as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f64::INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = f64::INFINITY as u128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = f64::NEG_INFINITY as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: u16 = f64::NEG_INFINITY as u16; force(X); } //~ ERROR constant evaluation error
+    { const X: i64 = f64::NEG_INFINITY as i64; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = f64::NEG_INFINITY as i128; force(X); } //~ ERROR constant evaluation error
+
+    { const X: u8 = 256. as u8; force(X); } //~ ERROR constant evaluation error
+    { const X: i8 = -129. as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i8 = 128. as i8; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = 2147483648. as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: i32 = -2147483904. as i32; force(X); } //~ ERROR constant evaluation error
+    { const X: u32 = 4294967296. as u32; force(X); } //~ ERROR constant evaluation error
+    { const X: u128 = 1e40 as u128; force(X); } //~ ERROR constant evaluation error
+    { const X: i128 = 1e40 as i128; force(X); } //~ ERROR constant evaluation error
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/invalid-inline.rs b/src/test/compile-fail/invalid-inline.rs
index ad89087d660..93b985b4fb0 100644
--- a/src/test/compile-fail/invalid-inline.rs
+++ b/src/test/compile-fail/invalid-inline.rs
@@ -21,4 +21,8 @@ fn b() {
 fn c() {
 }
 
-fn main() {}
+fn main() {
+    a();
+    b();
+    c();
+}
diff --git a/src/test/compile-fail/issue-16338.rs b/src/test/compile-fail/issue-16338.rs
index a4517e60d66..6fdf8802e38 100644
--- a/src/test/compile-fail/issue-16338.rs
+++ b/src/test/compile-fail/issue-16338.rs
@@ -16,7 +16,6 @@ struct Slice<T> {
 fn main() {
     let Slice { data: data, len: len } = "foo";
     //~^ ERROR mismatched types
-    //~| expected type `&str`
     //~| found type `Slice<_>`
-    //~| expected &str, found struct `Slice`
+    //~| ERROR non-reference pattern used to match a reference
 }
diff --git a/src/test/compile-fail/issue-20261.rs b/src/test/compile-fail/issue-20261.rs
index 7b5e61380f2..092aaa76955 100644
--- a/src/test/compile-fail/issue-20261.rs
+++ b/src/test/compile-fail/issue-20261.rs
@@ -10,7 +10,8 @@
 
 fn main() {
     // NB: this (almost) typechecks when default binding modes are enabled.
-    for (ref i,) in [].iter() { //~ ERROR mismatched types [E0308]
+    for (ref i,) in [].iter() {
+        //~^ ERROR non-reference pattern used to match a reference
         i.clone();
     }
 }
diff --git a/src/test/compile-fail/issue-22638.rs b/src/test/compile-fail/issue-22638.rs
index 65d1d837d7d..53b0d9f4e9f 100644
--- a/src/test/compile-fail/issue-22638.rs
+++ b/src/test/compile-fail/issue-22638.rs
@@ -12,6 +12,7 @@
 
 #![recursion_limit = "20"]
 #![type_length_limit = "20000000"]
+#![crate_type = "rlib"]
 
 #[derive(Clone)]
 struct A (B);
@@ -66,5 +67,3 @@ impl D {
 pub fn matches() {
     A(B::Variant1).matches(&(|| ()))
 }
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs
index 9d20c17674b..bf44cd53f67 100644
--- a/src/test/compile-fail/issue-23080-2.rs
+++ b/src/test/compile-fail/issue-23080-2.rs
@@ -17,6 +17,7 @@ unsafe trait Trait {
     type Output;
 }
 
+#[allow(auto_impl)]
 unsafe impl Trait for .. {}
 
 fn call_method<T: Trait>(x: T) {}
diff --git a/src/test/compile-fail/issue-23080.rs b/src/test/compile-fail/issue-23080.rs
index 2e8cba87be5..1fb63391d56 100644
--- a/src/test/compile-fail/issue-23080.rs
+++ b/src/test/compile-fail/issue-23080.rs
@@ -19,6 +19,7 @@ unsafe trait Trait {
     }
 }
 
+#[allow(auto_impl)]
 unsafe impl Trait for .. {}
 
 fn call_method<T: Trait>(x: T) {
diff --git a/src/test/compile-fail/keyword-false-as-identifier.rs b/src/test/compile-fail/keyword-false-as-identifier.rs
index e8af94f16b1..f246d6e75df 100644
--- a/src/test/compile-fail/keyword-false-as-identifier.rs
+++ b/src/test/compile-fail/keyword-false-as-identifier.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let false = "foo"; //~ error: mismatched types
+    let false = 22; //~ error: mismatched types
 }
diff --git a/src/test/compile-fail/keyword-self-as-identifier.rs b/src/test/compile-fail/keyword-self-as-identifier.rs
index f01aab92356..b50fc68bed6 100644
--- a/src/test/compile-fail/keyword-self-as-identifier.rs
+++ b/src/test/compile-fail/keyword-self-as-identifier.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let Self = "foo"; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+    let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
 }
diff --git a/src/test/compile-fail/keyword-super-as-identifier.rs b/src/test/compile-fail/keyword-super-as-identifier.rs
index 62649ba8a0f..54dac771f01 100644
--- a/src/test/compile-fail/keyword-super-as-identifier.rs
+++ b/src/test/compile-fail/keyword-super-as-identifier.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let super = "foo"; //~ ERROR failed to resolve. There are too many initial `super`s
+    let super = 22; //~ ERROR failed to resolve. There are too many initial `super`s
 }
diff --git a/src/test/compile-fail/keyword-true-as-identifier.rs b/src/test/compile-fail/keyword-true-as-identifier.rs
index 90414fa912d..b09d09db560 100644
--- a/src/test/compile-fail/keyword-true-as-identifier.rs
+++ b/src/test/compile-fail/keyword-true-as-identifier.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let true = "foo"; //~ error: mismatched types
+    let true = 22; //~ error: mismatched types
 }
diff --git a/src/test/compile-fail/match-range-fail.rs b/src/test/compile-fail/match-range-fail.rs
index f89b3e39390..355ff6404ce 100644
--- a/src/test/compile-fail/match-range-fail.rs
+++ b/src/test/compile-fail/match-range-fail.rs
@@ -15,6 +15,7 @@ fn main() {
     //~^^ ERROR only char and numeric types are allowed in range
     //~| start type: &'static str
     //~| end type: &'static str
+    //~| ERROR non-reference pattern used to match a reference
 
     match "wow" {
         10 ... "what" => ()
@@ -22,6 +23,7 @@ fn main() {
     //~^^ ERROR only char and numeric types are allowed in range
     //~| start type: {integer}
     //~| end type: &'static str
+    //~| ERROR non-reference pattern used to match a reference
 
     match 5 {
         'c' ... 100 => { }
diff --git a/src/test/compile-fail/match-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs
index d72ec8ba408..fed68da0068 100644
--- a/src/test/compile-fail/match-vec-mismatch.rs
+++ b/src/test/compile-fail/match-vec-mismatch.rs
@@ -19,7 +19,7 @@ fn main() {
 
     // Note that this one works with default binding modes.
     match &[0, 1, 2] {
-        [..] => {} //~ ERROR expected an array or slice, found `&[{integer}; 3]` [E0529]
+        [..] => {} //~ ERROR non-reference pattern used to match a reference
     };
 
     match &[0, 1, 2] {
diff --git a/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs b/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs
new file mode 100644
index 00000000000..c02977f22ea
--- /dev/null
+++ b/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs
@@ -0,0 +1,50 @@
+// Copyright 2012 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:-Zborrowck-mir -Znll
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut data = ('a', 'b', 'c');
+    let c = &mut data.0;
+    capitalize(c);
+    data.0 = 'e';
+    //~^ ERROR (Ast) [E0506]
+    //~| ERROR (Mir) [E0506]
+    data.0 = 'f';
+    //~^ ERROR (Ast) [E0506]
+    //~| ERROR (Mir) [E0506]
+    data.0 = 'g';
+    //~^ ERROR (Ast) [E0506]
+    //~| ERROR (Mir) [E0506]
+    capitalize(c);
+}
+
+fn nll_ok() {
+    let mut data = ('a', 'b', 'c');
+    let c = &mut data.0;
+    capitalize(c);
+    data.0 = 'e';
+    //~^ ERROR (Ast) [E0506]
+    data.0 = 'f';
+    //~^ ERROR (Ast) [E0506]
+    data.0 = 'g';
+    //~^ ERROR (Ast) [E0506]
+}
+
+fn capitalize(_: &mut char) {
+}
diff --git a/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs b/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs
new file mode 100644
index 00000000000..5e3a003b54e
--- /dev/null
+++ b/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs
@@ -0,0 +1,49 @@
+// Copyright 2012 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:-Zborrowck-mir -Znll
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut data = vec!['a', 'b', 'c'];
+    let slice = &mut data;
+    capitalize(slice);
+    data.push('d');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    data.push('e');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    data.push('f');
+    //~^ ERROR (Ast) [E0499]
+    //~| ERROR (Mir) [E0499]
+    capitalize(slice);
+}
+
+fn nll_ok() {
+    let mut data = vec!['a', 'b', 'c'];
+    let slice = &mut data;
+    capitalize(slice);
+    data.push('d');
+    //~^ ERROR (Ast) [E0499]
+    data.push('e');
+    //~^ ERROR (Ast) [E0499]
+    data.push('f');
+    //~^ ERROR (Ast) [E0499]
+}
+
+fn capitalize(_: &mut [char]) {
+}
diff --git a/src/test/compile-fail/nll/region-ends-after-if-condition.rs b/src/test/compile-fail/nll/region-ends-after-if-condition.rs
new file mode 100644
index 00000000000..bec56982c57
--- /dev/null
+++ b/src/test/compile-fail/nll/region-ends-after-if-condition.rs
@@ -0,0 +1,46 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Zborrowck-mir -Znll
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+struct MyStruct {
+    field: String
+}
+
+fn foo1() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &my_struct.field;
+    if value.is_empty() {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0502]
+    }
+}
+
+fn foo2() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &my_struct.field;
+    if value.is_empty() {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0502]
+        //~| ERROR (Mir) [E0502]
+    }
+    drop(value);
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/nll/return_from_loop.rs b/src/test/compile-fail/nll/return_from_loop.rs
new file mode 100644
index 00000000000..6b287fd2272
--- /dev/null
+++ b/src/test/compile-fail/nll/return_from_loop.rs
@@ -0,0 +1,49 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Zborrowck-mir -Znll
+
+#![allow(warnings)]
+#![feature(rustc_attrs)]
+
+struct MyStruct {
+    field: String
+}
+
+fn main() {
+}
+
+fn nll_fail() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &mut my_struct.field;
+    loop {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0499]
+        //~| ERROR (Mir) [E0499]
+        value.len();
+        return;
+    }
+}
+
+fn nll_ok() {
+    let mut my_struct = MyStruct { field: format!("Hello") };
+
+    let value = &mut my_struct.field;
+    loop {
+        my_struct.field.push_str("Hello, world!");
+        //~^ ERROR (Ast) [E0499]
+        return;
+    }
+}
diff --git a/src/test/compile-fail/non-interger-atomic.rs b/src/test/compile-fail/non-interger-atomic.rs
index 50240b47557..a51a9e518ce 100644
--- a/src/test/compile-fail/non-interger-atomic.rs
+++ b/src/test/compile-fail/non-interger-atomic.rs
@@ -10,92 +10,91 @@
 
 #![feature(core_intrinsics)]
 #![allow(warnings)]
+#![crate_type = "rlib"]
 
 use std::intrinsics;
 
 #[derive(Copy, Clone)]
-struct Foo(i64);
-type Bar = &'static Fn();
-type Quux = [u8; 100];
+pub struct Foo(i64);
+pub type Bar = &'static Fn();
+pub type Quux = [u8; 100];
 
-unsafe fn test_bool_load(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_store(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
+pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
 }
 
-unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
+pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
 }
 
-unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
     intrinsics::atomic_load(p);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
+pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
 }
 
-unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
     intrinsics::atomic_load(p);
     //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
     intrinsics::atomic_store(p, v);
     //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_xchg(p, v);
     //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
 }
 
-unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
+pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_cxchg(p, v, v);
     //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
 }
-
-fn main() {}
diff --git a/src/test/compile-fail/pat-slice-old-style.rs b/src/test/compile-fail/pat-slice-old-style.rs
index 54028ffa63f..d49ce56ccf6 100644
--- a/src/test/compile-fail/pat-slice-old-style.rs
+++ b/src/test/compile-fail/pat-slice-old-style.rs
@@ -17,8 +17,9 @@ fn slice_pat(x: &[u8]) {
     // OLD!
     match x {
         [a, b..] => {},
-        //~^ ERROR expected an array or slice, found `&[u8]`
-        //~| HELP the semantics of slice patterns changed recently; see issue #23121
+        //~^ ERROR non-reference pattern used to match a reference
+        //~| HELP add #![feature(match_default_bindings)] to the crate attributes to enable
+        //~| HELP consider using
         _ => panic!(),
     }
 }
diff --git a/src/test/compile-fail/phantom-oibit.rs b/src/test/compile-fail/phantom-oibit.rs
index c84927ea266..1c1cb396a54 100644
--- a/src/test/compile-fail/phantom-oibit.rs
+++ b/src/test/compile-fail/phantom-oibit.rs
@@ -18,6 +18,7 @@ use std::marker::{PhantomData};
 
 unsafe trait Zen {}
 
+#[allow(auto_impl)]
 unsafe impl Zen for .. {}
 
 unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
diff --git a/src/test/compile-fail/privacy-sanity.rs b/src/test/compile-fail/privacy-sanity.rs
index 933ec3837df..34082adb8f9 100644
--- a/src/test/compile-fail/privacy-sanity.rs
+++ b/src/test/compile-fail/privacy-sanity.rs
@@ -21,6 +21,7 @@ pub struct S {
 }
 struct Ts(pub u8);
 
+#[allow(auto_impl)]
 pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
 pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
     pub fn f() {} //~ ERROR unnecessary visibility qualifier
@@ -49,6 +50,7 @@ const MAIN: u8 = {
     }
     struct Ts(pub u8);
 
+    #[allow(auto_impl)]
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
@@ -80,6 +82,7 @@ fn main() {
     }
     struct Ts(pub u8);
 
+    #[allow(auto_impl)]
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
diff --git a/src/test/compile-fail/regions-infer-at-fn-not-param.rs b/src/test/compile-fail/regions-infer-at-fn-not-param.rs
index 0c250e38258..ec73bf90b6e 100644
--- a/src/test/compile-fail/regions-infer-at-fn-not-param.rs
+++ b/src/test/compile-fail/regions-infer-at-fn-not-param.rs
@@ -21,7 +21,7 @@ struct not_parameterized2 {
 }
 
 fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
-//~^ ERROR mismatched types
+//~^ ERROR explicit lifetime required in the type of `p`
 
 fn take3(p: not_parameterized1) -> not_parameterized1 { p }
 fn take4(p: not_parameterized2) -> not_parameterized2 { p }
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644
index 00000000000..12d1bf9ea91
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -0,0 +1,19 @@
+// Copyright 2012 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644
index 00000000000..4d083cc5315
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -0,0 +1,37 @@
+// Copyright 2012 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(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct FunctionalRecord {
+    pub first_field: u16,
+    pub second_field: u16,
+    pub third_field: bool
+}
+
+impl Default for FunctionalRecord {
+    fn default() -> FunctionalRecord {
+        FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
+    }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644
index 00000000000..d04c1073ad9
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs
@@ -0,0 +1,18 @@
+// Copyright 2012 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs
new file mode 100644
index 00000000000..0c19210e4a0
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs
@@ -0,0 +1,25 @@
+// Copyright 2012 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.
+
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third"
+    };
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs
new file mode 100644
index 00000000000..74c9c7c61ac
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs
@@ -0,0 +1,47 @@
+// Copyright 2012 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.
+
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord};
+
+fn main() {
+    let fr = FunctionalRecord {
+    //~^ ERROR cannot create non-exhaustive struct
+        first_field: 1920,
+        second_field: 1080,
+        ..FunctionalRecord::default()
+    };
+
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+    //~^ ERROR cannot create non-exhaustive struct
+
+    let NormalStruct { first_field, second_field } = ns;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let ts = TupleStruct(640, 480);
+    //~^ ERROR expected function, found struct `TupleStruct` [E0423]
+
+    let ts_explicit = structs::TupleStruct(640, 480);
+    //~^ ERROR tuple struct `TupleStruct` is private [E0603]
+
+    let TupleStruct { 0: first_field, 1: second_field } = ts;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let us = UnitStruct;
+    //~^ ERROR expected value, found struct `UnitStruct` [E0423]
+
+    let us_explicit = structs::UnitStruct;
+    //~^ ERROR unit struct `UnitStruct` is private [E0603]
+
+    let UnitStruct { } = us;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs
new file mode 100644
index 00000000000..d1b65ac1f3e
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs
@@ -0,0 +1,36 @@
+// Copyright 2012 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.
+
+// aux-build:variants.rs
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+fn main() {
+    let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+    //~^ ERROR cannot create non-exhaustive variant
+
+    let variant_tuple = NonExhaustiveVariants::Tuple { 0: 640 };
+    //~^ ERROR cannot create non-exhaustive variant
+
+    match variant_struct {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+        NonExhaustiveVariants::Struct { field } => ""
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+    };
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs
new file mode 100644
index 00000000000..f4e4b1bb84b
--- /dev/null
+++ b/src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs
@@ -0,0 +1,27 @@
+// Copyright 2012 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(non_exhaustive)]
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+    #[non_exhaustive] Tuple(u32),
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+    #[non_exhaustive] Struct { field: u32 }
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/self-vs-path-ambiguity.rs b/src/test/compile-fail/self-vs-path-ambiguity.rs
index 9753014e781..b2dba3bd61b 100644
--- a/src/test/compile-fail/self-vs-path-ambiguity.rs
+++ b/src/test/compile-fail/self-vs-path-ambiguity.rs
@@ -17,7 +17,6 @@ impl S {
     fn g(&self::S: &S) {}
     fn h(&mut self::S: &mut S) {}
     fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern
-                             //~^ ERROR expected one of `)` or `mut`, found `'a`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
index c1746d765dd..cad43ffeace 100644
--- a/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
+++ b/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
@@ -13,7 +13,8 @@
 
 trait Foo {}
 
+#[allow(auto_impl)]
 default impl Foo for .. {}
-//~^ ERROR `default impl` is not allowed for default trait implementations
+//~^ ERROR `default impl` is not allowed for auto trait implementations
 
 fn main() {}
diff --git a/src/test/compile-fail/specialization/specialization-polarity.rs b/src/test/compile-fail/specialization/specialization-polarity.rs
index 27a3e31491b..c97cb3f6bb7 100644
--- a/src/test/compile-fail/specialization/specialization-polarity.rs
+++ b/src/test/compile-fail/specialization/specialization-polarity.rs
@@ -15,6 +15,7 @@
 
 trait Foo {}
 
+#[allow(auto_impl)]
 impl Foo for .. {}
 
 impl<T> Foo for T {}
@@ -22,6 +23,7 @@ impl !Foo for u8 {} //~ ERROR E0119
 
 trait Bar {}
 
+#[allow(auto_impl)]
 impl Bar for .. {}
 
 impl<T> !Bar for T {}
diff --git a/src/test/compile-fail/syntaxt-default-trait-impls.rs b/src/test/compile-fail/syntaxt-default-trait-impls.rs
index 7d6a1c9c154..45303cbf700 100644
--- a/src/test/compile-fail/syntaxt-default-trait-impls.rs
+++ b/src/test/compile-fail/syntaxt-default-trait-impls.rs
@@ -10,9 +10,10 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyDefaultImpl {}
+trait MyAutoImpl {}
 
-impl<T> MyDefaultImpl for .. {}
-//~^ ERROR default trait implementations are not allowed to have generics
+#[allow(auto_impl)]
+impl<T> MyAutoImpl for .. {}
+//~^ ERROR auto trait implementations are not allowed to have generics
 
 fn main() {}
diff --git a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
index fe0e583b20a..6c7928f13f8 100644
--- a/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
+++ b/src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
@@ -15,6 +15,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic: Copy {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
diff --git a/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
index f6678ac7c2d..173582ed22f 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
@@ -11,6 +11,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 impl<T:Magic> Magic for T {}
 
diff --git a/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
index 9497dfb39d7..6802f72504b 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
@@ -35,6 +35,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic: Copy {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 impl<T:Magic> Magic for T {}
 
diff --git a/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs b/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
index 5a852c54869..3c409d1b371 100644
--- a/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
+++ b/src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
@@ -11,4 +11,5 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic<T> {} //~ ERROR E0567
+#[allow(auto_impl)]
 impl Magic<isize> for .. {}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
index 8a46d6c76c3..a837d8c9ca7 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
@@ -12,6 +12,7 @@
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 struct MyS;
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
index 3d7746b369c..bed184eb4cc 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
@@ -12,6 +12,7 @@
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 impl<T> !MyTrait for *mut T {}
 
diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs
index 8c2658b89a5..f3a6d8a342e 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-negation.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-negation.rs
@@ -12,10 +12,12 @@
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 unsafe trait MyUnsafeTrait {}
 
+#[allow(auto_impl)]
 unsafe impl MyUnsafeTrait for .. {}
 
 struct ThisImplsTrait;
diff --git a/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs
index 4d71517e060..da3e926d6fc 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs
@@ -10,6 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
+#[allow(auto_impl)]
 impl Copy for .. {} //~ ERROR E0318
      //~^ NOTE `Copy` trait not defined in this crate
 fn main() {}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
index 66c7a1c75ff..bdd6487b86d 100644
--- a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
+++ b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
@@ -16,6 +16,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Defaulted { }
+#[allow(auto_impl)]
 impl Defaulted for .. { }
 impl<'a,T:Signed> Defaulted for &'a T { }
 impl<'a,T:Signed> Defaulted for &'a mut T { }
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
index 40067efd575..067ce51d0f7 100644
--- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
@@ -12,27 +12,29 @@
 // crate. This should not cause anything we use to be invalidated.
 // Regression test for #36168.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_free_fn", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -40,10 +42,10 @@ mod fn_calls_methods_in_same_impl {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_free_fn {
+pub mod fn_calls_free_fn {
     use point::{self, Point};
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         point::distance_squared(&x);
@@ -51,34 +53,31 @@ mod fn_calls_free_fn {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
index ac5c0d3b9e7..b1c566e1739 100644
--- a/src/test/incremental/change_add_field/struct_point.rs
+++ b/src/test/incremental/change_add_field/struct_point.rs
@@ -13,32 +13,34 @@
 // Fns with that type used only in their body are also recompiled, but
 // their callers are not.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
 // These are expected to require translation.
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_with_type_in_sig", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-call_fn_with_type_in_sig", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_with_type_in_body", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="rpass2")]
-
-#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="rpass2")]
-
-mod point {
-    #[cfg(rpass1)]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-call_fn_with_type_in_sig", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_with_type_in_body", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="cfail2")]
+
+#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="cfail2")]
+
+pub mod point {
+    #[cfg(cfail1)]
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
-    #[cfg(rpass2)]
+    #[cfg(cfail2)]
     pub struct Point {
         pub x: f32,
         pub y: f32,
@@ -47,18 +49,18 @@ mod point {
 
     impl Point {
         pub fn origin() -> Point {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return Point { x: 0.0, y: 0.0 };
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return Point { x: 0.0, y: 0.0, z: 0.0 };
         }
 
         pub fn total(&self) -> f32 {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return self.x + self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return self.x + self.y + self.z;
         }
 
@@ -75,10 +77,10 @@ mod point {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod fn_with_type_in_sig {
+pub mod fn_with_type_in_sig {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn boop(p: Option<&Point>) -> f32 {
         p.map(|p| p.total()).unwrap_or(0.0)
     }
@@ -91,10 +93,10 @@ mod fn_with_type_in_sig {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod call_fn_with_type_in_sig {
+pub mod call_fn_with_type_in_sig {
     use fn_with_type_in_sig;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_sig::boop(None)
     }
@@ -107,10 +109,10 @@ mod call_fn_with_type_in_sig {
 /// sufficiently "private", we might not need to type-check again.
 /// Rebuilding is probably always necessary since the layout may be
 /// affected.
-mod fn_with_type_in_body {
+pub mod fn_with_type_in_body {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn boop() -> f32 {
         Point::origin().total()
     }
@@ -120,44 +122,41 @@ mod fn_with_type_in_body {
 /// body. In this case, the effects of the change should be contained
 /// to Y; X should not have to be rebuilt, nor should it need to be
 /// typechecked again.
-mod call_fn_with_type_in_body {
+pub mod call_fn_with_type_in_body {
     use fn_with_type_in_body;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_body::boop()
     }
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin(p: Point) -> Point {
         Point { ..p }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_private_fn/struct_point.rs b/src/test/incremental/change_private_fn/struct_point.rs
index abfd55ba52c..d8251a4fbcf 100644
--- a/src/test/incremental/change_private_fn/struct_point.rs
+++ b/src/test/incremental/change_private_fn/struct_point.rs
@@ -11,32 +11,34 @@
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     fn distance_squared(this: &Point) -> f32 {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         return this.x + this.y;
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         return this.x * this.x + this.y * this.y;
     }
 
@@ -56,10 +58,10 @@ mod point {
 }
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -67,10 +69,10 @@ mod fn_calls_methods_in_same_impl {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -78,34 +80,31 @@ mod fn_calls_methods_in_another_impl {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_private_fn_cc/auxiliary/point.rs b/src/test/incremental/change_private_fn_cc/auxiliary/point.rs
index dcc1ced635f..af20336806f 100644
--- a/src/test/incremental/change_private_fn_cc/auxiliary/point.rs
+++ b/src/test/incremental/change_private_fn_cc/auxiliary/point.rs
@@ -14,10 +14,10 @@ pub struct Point {
 }
 
 fn distance_squared(this: &Point) -> f32 {
-    #[cfg(rpass1)]
+    #[cfg(cfail1)]
     return this.x + this.y;
 
-    #[cfg(rpass2)]
+    #[cfg(cfail2)]
     return this.x * this.x + this.y * this.y;
 }
 
diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs
index a6d029515d7..b3816b90194 100644
--- a/src/test/incremental/change_private_fn_cc/struct_point.rs
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -11,27 +11,29 @@
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -39,10 +41,10 @@ mod fn_calls_methods_in_same_impl {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -50,34 +52,31 @@ mod fn_calls_methods_in_another_impl {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs
index d8c6cafe596..c18f95a6312 100644
--- a/src/test/incremental/change_private_impl_method/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method/struct_point.rs
@@ -11,33 +11,35 @@
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
+#![crate_type = "rlib"]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     impl Point {
-        fn distance_squared(&self) -> f32 {
-            #[cfg(rpass1)]
+        pub fn distance_squared(&self) -> f32 {
+            #[cfg(cfail1)]
             return self.x + self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return self.x * self.x + self.y * self.y;
         }
 
@@ -56,10 +58,10 @@ mod point {
 }
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -67,10 +69,10 @@ mod fn_calls_methods_in_same_impl {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -78,34 +80,31 @@ mod fn_calls_methods_in_another_impl {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs b/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
index 8df1cf54da2..f5e3a06051c 100644
--- a/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
+++ b/src/test/incremental/change_private_impl_method_cc/auxiliary/point.rs
@@ -15,10 +15,10 @@ pub struct Point {
 
 impl Point {
     fn distance_squared(&self) -> f32 {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         return self.x + self.y;
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         return self.x * self.x + self.y * self.y;
     }
 
diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
index 05c076b9f4b..55e1dffe9da 100644
--- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
@@ -11,28 +11,30 @@
 // Test where we change the body of a private method in an impl.
 // We then test what sort of functions must be rebuilt as a result.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="cfail2")]
 
 extern crate point;
 
 /// A fn item that calls (public) methods on `Point` from the same impl which changed
-mod fn_calls_methods_in_same_impl {
+pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -40,10 +42,10 @@ mod fn_calls_methods_in_same_impl {
 }
 
 /// A fn item that calls (public) methods on `Point` from another impl
-mod fn_calls_methods_in_another_impl {
+pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn dirty() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -51,34 +53,31 @@ mod fn_calls_methods_in_another_impl {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
index 5b29ee1435f..2cb7ef13f8e 100644
--- a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
@@ -10,22 +10,24 @@
 
 // Test where we change the body of a public, inherent method.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_changed_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
@@ -33,10 +35,10 @@ mod point {
 
     impl Point {
         pub fn distance_from_origin(&self) -> f32 {
-            #[cfg(rpass1)]
+            #[cfg(cfail1)]
             return self.x * self.x + self.y * self.y;
 
-            #[cfg(rpass2)]
+            #[cfg(cfail2)]
             return (self.x * self.x + self.y * self.y).sqrt();
         }
 
@@ -47,10 +49,10 @@ mod point {
 }
 
 /// A fn item that calls the method on `Point` which changed
-mod fn_calls_changed_method {
+pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_origin();
@@ -58,10 +60,10 @@ mod fn_calls_changed_method {
 }
 
 /// A fn item that calls a method on `Point` which did not change
-mod fn_calls_another_method {
+pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -69,34 +71,31 @@ mod fn_calls_another_method {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
index 4d12b7b390c..f2485a876cc 100644
--- a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
@@ -10,30 +10,32 @@
 
 // Test where we change the *signature* of a public, inherent method.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
 
 // These are expected to require translation.
-#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")]
-#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="rpass2")]
+#![rustc_partition_translated(module="struct_point-point", cfg="cfail2")]
+#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="cfail2")]
 
-#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")]
-#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")]
+#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="cfail2")]
+#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="cfail2")]
 
-mod point {
+pub mod point {
     pub struct Point {
         pub x: f32,
         pub y: f32,
     }
 
     impl Point {
-        #[cfg(rpass1)]
+        #[cfg(cfail1)]
         pub fn distance_from_point(&self, p: Option<Point>) -> f32 {
             let p = p.unwrap_or(Point { x: 0.0, y: 0.0 });
             let x_diff = self.x - p.x;
@@ -41,7 +43,7 @@ mod point {
             return x_diff * x_diff + y_diff * y_diff;
         }
 
-        #[cfg(rpass2)]
+        #[cfg(cfail2)]
         pub fn distance_from_point(&self, p: Option<&Point>) -> f32 {
             const ORIGIN: &Point = &Point { x: 0.0, y: 0.0 };
             let p = p.unwrap_or(ORIGIN);
@@ -57,10 +59,10 @@ mod point {
 }
 
 /// A fn item that calls the method that was changed
-mod fn_calls_changed_method {
+pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_point(None);
@@ -68,10 +70,10 @@ mod fn_calls_changed_method {
 }
 
 /// A fn item that calls a method that was not changed
-mod fn_calls_another_method {
+pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -79,34 +81,31 @@ mod fn_calls_another_method {
 }
 
 /// A fn item that makes an instance of `Point` but does not invoke methods
-mod fn_make_struct {
+pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
 }
 
 /// A fn item that reads fields from `Point` but does not invoke methods
-mod fn_read_field {
+pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
 }
 
 /// A fn item that writes to a field of `Point` but does not invoke methods
-mod fn_write_field {
+pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
 }
-
-fn main() {
-}
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index 0090c2aeef9..b49609cbd17 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -190,7 +190,7 @@ impl Struct2 {
 }
 
 // Change UFCS Callee Indirectly -----------------------------------------------
-mod change_ufcs_callee_indirectly {
+pub mod change_ufcs_callee_indirectly {
     #[cfg(cfail1)]
     use super::Struct as Struct;
     #[cfg(not(cfail1))]
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index f826d47c3e5..e38fd58d7d2 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -25,7 +25,7 @@
 #![crate_type="rlib"]
 
 
-enum Enum {
+pub enum Enum {
     Struct {
         x: i32,
         y: i64,
@@ -36,7 +36,7 @@ enum Enum {
 
 // Change field value (struct-like) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_struct_like() -> Enum {
+pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
         y: 1,
@@ -49,7 +49,7 @@ fn change_field_value_struct_like() -> Enum {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_struct_like() -> Enum {
+pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
         y: 2,
@@ -61,7 +61,7 @@ fn change_field_value_struct_like() -> Enum {
 
 // Change field order (struct-like) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_order_struct_like() -> Enum {
+pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         x: 3,
         y: 4,
@@ -76,7 +76,7 @@ fn change_field_order_struct_like() -> Enum {
 #[rustc_metadata_clean(cfg="cfail3")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
-fn change_field_order_struct_like() -> Enum {
+pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         y: 4,
         x: 3,
@@ -85,7 +85,7 @@ fn change_field_order_struct_like() -> Enum {
 }
 
 
-enum Enum2 {
+pub enum Enum2 {
     Struct {
         x: i8,
         y: i8,
@@ -102,7 +102,7 @@ enum Enum2 {
 
 // Change constructor path (struct-like) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_struct_like() {
+pub fn change_constructor_path_struct_like() {
     let _ = Enum::Struct {
         x: 0,
         y: 1,
@@ -115,7 +115,7 @@ fn change_constructor_path_struct_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_struct_like() {
+pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
         y: 1,
@@ -127,7 +127,7 @@ fn change_constructor_path_struct_like() {
 
 // Change variant (regular struct) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_struct_like() {
+pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
         y: 1,
@@ -140,7 +140,7 @@ fn change_constructor_variant_struct_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_struct_like() {
+pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
         x: 0,
         y: 1,
@@ -150,7 +150,7 @@ fn change_constructor_variant_struct_like() {
 
 
 // Change constructor path indirectly (struct-like) -------------------------
-mod change_constructor_path_indirectly_struct_like {
+pub mod change_constructor_path_indirectly_struct_like {
     #[cfg(cfail1)]
     use super::Enum as TheEnum;
     #[cfg(not(cfail1))]
@@ -164,7 +164,7 @@ mod change_constructor_path_indirectly_struct_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::Struct {
             x: 0,
             y: 1,
@@ -175,7 +175,7 @@ mod change_constructor_path_indirectly_struct_like {
 
 
 // Change constructor variant indirectly (struct-like) ---------------------------
-mod change_constructor_variant_indirectly_struct_like {
+pub mod change_constructor_variant_indirectly_struct_like {
     use super::Enum2;
     #[cfg(cfail1)]
     use super::Enum2::Struct as Variant;
@@ -186,7 +186,7 @@ mod change_constructor_variant_indirectly_struct_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Enum2 {
+    pub fn function() -> Enum2 {
         Variant {
             x: 0,
             y: 1,
@@ -198,7 +198,7 @@ mod change_constructor_variant_indirectly_struct_like {
 
 // Change field value (tuple-like) -------------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_tuple_like() -> Enum {
+pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 2)
 }
 
@@ -207,7 +207,7 @@ fn change_field_value_tuple_like() -> Enum {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_tuple_like() -> Enum {
+pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
 }
 
@@ -215,7 +215,7 @@ fn change_field_value_tuple_like() -> Enum {
 
 // Change constructor path (tuple-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_tuple_like() {
+pub fn change_constructor_path_tuple_like() {
     let _ = Enum::Tuple(0, 1, 2);
 }
 
@@ -227,7 +227,7 @@ fn change_constructor_path_tuple_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_tuple_like() {
+pub fn change_constructor_path_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
 
@@ -235,7 +235,7 @@ fn change_constructor_path_tuple_like() {
 
 // Change constructor variant (tuple-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_tuple_like() {
+pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
 
@@ -247,13 +247,13 @@ fn change_constructor_variant_tuple_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_tuple_like() {
+pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple2(0, 1, 2);
 }
 
 
 // Change constructor path indirectly (tuple-like) ---------------------------
-mod change_constructor_path_indirectly_tuple_like {
+pub mod change_constructor_path_indirectly_tuple_like {
     #[cfg(cfail1)]
     use super::Enum as TheEnum;
     #[cfg(not(cfail1))]
@@ -267,7 +267,7 @@ mod change_constructor_path_indirectly_tuple_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::Tuple(0, 1, 2)
     }
 }
@@ -275,7 +275,7 @@ mod change_constructor_path_indirectly_tuple_like {
 
 
 // Change constructor variant indirectly (tuple-like) ---------------------------
-mod change_constructor_variant_indirectly_tuple_like {
+pub mod change_constructor_variant_indirectly_tuple_like {
     use super::Enum2;
     #[cfg(cfail1)]
     use super::Enum2::Tuple as Variant;
@@ -286,19 +286,19 @@ mod change_constructor_variant_indirectly_tuple_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Enum2 {
+    pub fn function() -> Enum2 {
         Variant(0, 1, 2)
     }
 }
 
 
-enum Clike {
+pub enum Clike {
     A,
     B,
     C
 }
 
-enum Clike2 {
+pub enum Clike2 {
     B,
     C,
     D
@@ -306,7 +306,7 @@ enum Clike2 {
 
 // Change constructor path (C-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_c_like() {
+pub fn change_constructor_path_c_like() {
     let _ = Clike::B;
 }
 
@@ -314,7 +314,7 @@ fn change_constructor_path_c_like() {
 #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirValidated,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_c_like() {
+pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
 }
 
@@ -322,7 +322,7 @@ fn change_constructor_path_c_like() {
 
 // Change constructor variant (C-like) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_variant_c_like() {
+pub fn change_constructor_variant_c_like() {
     let _ = Clike::A;
 }
 
@@ -331,13 +331,13 @@ fn change_constructor_variant_c_like() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_variant_c_like() {
+pub fn change_constructor_variant_c_like() {
     let _ = Clike::C;
 }
 
 
 // Change constructor path indirectly (C-like) ---------------------------
-mod change_constructor_path_indirectly_c_like {
+pub mod change_constructor_path_indirectly_c_like {
     #[cfg(cfail1)]
     use super::Clike as TheEnum;
     #[cfg(not(cfail1))]
@@ -351,7 +351,7 @@ mod change_constructor_path_indirectly_c_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> TheEnum {
+    pub fn function() -> TheEnum {
         TheEnum::B
     }
 }
@@ -359,7 +359,7 @@ mod change_constructor_path_indirectly_c_like {
 
 
 // Change constructor variant indirectly (C-like) ---------------------------
-mod change_constructor_variant_indirectly_c_like {
+pub mod change_constructor_variant_indirectly_c_like {
     use super::Clike;
     #[cfg(cfail1)]
     use super::Clike::A as Variant;
@@ -370,7 +370,7 @@ mod change_constructor_variant_indirectly_c_like {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_clean(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Clike {
+    pub fn function() -> Clike {
         Variant
     }
 }
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 9351a4b05f1..f9e8fb026ca 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -25,7 +25,7 @@
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
-struct Foo;
+pub struct Foo;
 
 // Change Method Name -----------------------------------------------------------
 #[cfg(cfail1)]
@@ -578,3 +578,19 @@ impl<T: Clone> Bar<T> {
     #[rustc_metadata_clean(cfg="cfail3")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
+
+
+// Force instantiation of some fns so we can check their hash.
+pub fn instantiation_root() {
+    Foo::method_privacy();
+
+    #[cfg(cfail1)]
+    {
+        Bar(0u32).change_impl_self_type();
+    }
+
+    #[cfg(not(cfail1))]
+    {
+        Bar(0u64).change_impl_self_type();
+    }
+}
diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs
index 5d4d434fd63..4a3e4bc49ce 100644
--- a/src/test/incremental/hashes/panic_exprs.rs
+++ b/src/test/incremental/hashes/panic_exprs.rs
@@ -152,13 +152,48 @@ pub fn mod_by_zero(val: i32) -> i32 {
 }
 
 
+// shift left ------------------------------------------------------------------
+#[cfg(cfail1)]
+pub fn shift_left(val: i32, shift: usize) -> i32 {
+    val << shift
+}
+
+#[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_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_clean(cfg="cfail3")]
+pub fn shift_left(val: i32, shift: usize) -> i32 {
+    val << shift
+}
+
+
+// shift right ------------------------------------------------------------------
+#[cfg(cfail1)]
+pub fn shift_right(val: i32, shift: usize) -> i32 {
+    val >> shift
+}
+
+#[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_metadata_clean(cfg="cfail2")]
+#[rustc_metadata_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 << 1 >> 1
+    !val & 0x101010101 | 0x45689 ^ 0x2372382
 }
 
 #[cfg(not(cfail1))]
@@ -169,7 +204,7 @@ pub fn bitwise(val: i32) -> i32 {
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 pub fn bitwise(val: i32) -> i32 {
-    !val & 0x101010101 | 0x45689 ^ 0x2372382 << 1 >> 1
+    !val & 0x101010101 | 0x45689 ^ 0x2372382
 }
 
 
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index 231e29b79c4..67362e31b25 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -25,7 +25,7 @@
 #![crate_type="rlib"]
 
 
-struct RegularStruct {
+pub struct RegularStruct {
     x: i32,
     y: i64,
     z: i16,
@@ -33,7 +33,7 @@ struct RegularStruct {
 
 // Change field value (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_regular_struct() -> RegularStruct {
+pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
         y: 1,
@@ -46,7 +46,7 @@ fn change_field_value_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_regular_struct() -> RegularStruct {
+pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
         y: 2,
@@ -58,7 +58,7 @@ fn change_field_value_regular_struct() -> RegularStruct {
 
 // Change field order (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_order_regular_struct() -> RegularStruct {
+pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 3,
         y: 4,
@@ -71,7 +71,7 @@ fn change_field_order_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_order_regular_struct() -> RegularStruct {
+pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         y: 4,
         x: 3,
@@ -83,7 +83,7 @@ fn change_field_order_regular_struct() -> RegularStruct {
 
 // Add field (regular struct) --------------------------------------------------
 #[cfg(cfail1)]
-fn add_field_regular_struct() -> RegularStruct {
+pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -101,7 +101,7 @@ fn add_field_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn add_field_regular_struct() -> RegularStruct {
+pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -119,7 +119,7 @@ fn add_field_regular_struct() -> RegularStruct {
 
 // Change field label (regular struct) -----------------------------------------
 #[cfg(cfail1)]
-fn change_field_label_regular_struct() -> RegularStruct {
+pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -138,7 +138,7 @@ fn change_field_label_regular_struct() -> RegularStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_label_regular_struct() -> RegularStruct {
+pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
         y: 4,
@@ -154,7 +154,7 @@ fn change_field_label_regular_struct() -> RegularStruct {
 
 
 
-struct RegularStruct2 {
+pub struct RegularStruct2 {
     x: i8,
     y: i8,
     z: i8,
@@ -162,7 +162,7 @@ struct RegularStruct2 {
 
 // Change constructor path (regular struct) ------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_regular_struct() {
+pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct {
         x: 0,
         y: 1,
@@ -175,7 +175,7 @@ fn change_constructor_path_regular_struct() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_regular_struct() {
+pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
         x: 0,
         y: 1,
@@ -186,7 +186,7 @@ fn change_constructor_path_regular_struct() {
 
 
 // Change constructor path indirectly (regular struct) -------------------------
-mod change_constructor_path_indirectly_regular_struct {
+pub mod change_constructor_path_indirectly_regular_struct {
     #[cfg(cfail1)]
     use super::RegularStruct as Struct;
     #[cfg(not(cfail1))]
@@ -199,7 +199,7 @@ mod change_constructor_path_indirectly_regular_struct {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Struct {
+    pub fn function() -> Struct {
         Struct {
             x: 0,
             y: 1,
@@ -210,11 +210,11 @@ mod change_constructor_path_indirectly_regular_struct {
 
 
 
-struct TupleStruct(i32, i64, i16);
+pub struct TupleStruct(i32, i64, i16);
 
 // Change field value (tuple struct) -------------------------------------------
 #[cfg(cfail1)]
-fn change_field_value_tuple_struct() -> TupleStruct {
+pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 2)
 }
 
@@ -223,17 +223,17 @@ fn change_field_value_tuple_struct() -> TupleStruct {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_field_value_tuple_struct() -> TupleStruct {
+pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
 }
 
 
 
-struct TupleStruct2(u16, u16, u16);
+pub struct TupleStruct2(u16, u16, u16);
 
 // Change constructor path (tuple struct) --------------------------------------
 #[cfg(cfail1)]
-fn change_constructor_path_tuple_struct() {
+pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct(0, 1, 2);
 }
 
@@ -242,14 +242,14 @@ fn change_constructor_path_tuple_struct() {
 #[rustc_clean(cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-fn change_constructor_path_tuple_struct() {
+pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
 }
 
 
 
 // Change constructor path indirectly (tuple struct) ---------------------------
-mod change_constructor_path_indirectly_tuple_struct {
+pub mod change_constructor_path_indirectly_tuple_struct {
     #[cfg(cfail1)]
     use super::TupleStruct as Struct;
     #[cfg(not(cfail1))]
@@ -262,7 +262,7 @@ mod change_constructor_path_indirectly_tuple_struct {
     #[rustc_clean(cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
     #[rustc_metadata_clean(cfg="cfail3")]
-    fn function() -> Struct {
+    pub fn function() -> Struct {
         Struct(0, 1, 2)
     }
 }
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 44950ee8a60..108363a4645 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -249,7 +249,7 @@ trait TraitChangeMethodParametersOrder {
 
 // Add default implementation to method -------------------------------------------
 #[cfg(cfail1)]
-trait TraitAddMethodDefaultImplementation {
+trait TraitAddMethodAutoImplementation {
     fn method();
 }
 
@@ -258,7 +258,7 @@ trait TraitAddMethodDefaultImplementation {
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-trait TraitAddMethodDefaultImplementation {
+trait TraitAddMethodAutoImplementation {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index e8e40d57b1e..2e0f0ba0837 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -11,29 +11,29 @@
 // Check that the hash of `foo` doesn't change just because we ordered
 // the nested items (or even added new ones).
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
+// must-compile-successfully
 
+#![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[cfg(rpass1)]
-fn foo() {
-    fn bar() { }
-    fn baz() { }
+#[cfg(cfail1)]
+pub fn foo() {
+    pub fn bar() { }
+    pub fn baz() { }
 }
 
-#[cfg(rpass2)]
-#[rustc_clean(label="Hir", cfg="rpass2")]
-#[rustc_clean(label="HirBody", cfg="rpass2")]
-fn foo() {
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn baz() { } // order is different...
+#[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")]
+    pub fn baz() { } // order is different...
 
-    #[rustc_clean(label="Hir", cfg="rpass2")]
-    #[rustc_clean(label="HirBody", cfg="rpass2")]
-    fn bar() { } // but that doesn't matter.
+    #[rustc_clean(label="Hir", cfg="cfail2")]
+    #[rustc_clean(label="HirBody", cfg="cfail2")]
+    pub fn bar() { } // but that doesn't matter.
 
-    fn bap() { } // neither does adding a new item
+    pub fn bap() { } // neither does adding a new item
 }
-
-fn main() { }
diff --git a/src/test/incremental/issue-38222.rs b/src/test/incremental/issue-38222.rs
index 410ff69bf69..7bb8af74eeb 100644
--- a/src/test/incremental/issue-38222.rs
+++ b/src/test/incremental/issue-38222.rs
@@ -33,10 +33,9 @@ pub fn main() {
 
 mod mod1 {
     pub fn some_fn() {
-        let _ = 1;
-    }
+        #[cfg(rpass2)]
+        {}
 
-    #[cfg(rpass2)]
-    fn _some_other_fn() {
+        let _ = 1;
     }
 }
diff --git a/src/test/incremental/krate-inherent.rs b/src/test/incremental/krate-inherent.rs
index ac6cc3e9826..bc3e3a78fd6 100644
--- a/src/test/incremental/krate-inherent.rs
+++ b/src/test/incremental/krate-inherent.rs
@@ -8,27 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
-#![rustc_partition_reused(module="krate_inherent-x", cfg="rpass2")]
+#![rustc_partition_reused(module="krate_inherent-x", cfg="cfail2")]
+#![crate_type = "rlib"]
 
-fn main() { }
-
-mod x {
-    struct Foo;
+pub mod x {
+    pub struct Foo;
     impl Foo {
-        fn foo(&self) { }
+        pub fn foo(&self) { }
     }
 
-    fn method() {
+    pub fn method() {
         let x: Foo = Foo;
         x.foo(); // inherent methods used to add an edge from Krate
     }
 }
 
-#[cfg(rpass1)]
-fn bar() { } // remove this unrelated fn in rpass2, which should not affect `x::method`
+#[cfg(cfail1)]
+pub fn bar() { } // remove this unrelated fn in cfail2, which should not affect `x::method`
 
diff --git a/src/test/incremental/krate-inlined.rs b/src/test/incremental/krate-inlined.rs
index 043cb761da0..83b75116c60 100644
--- a/src/test/incremental/krate-inlined.rs
+++ b/src/test/incremental/krate-inlined.rs
@@ -20,12 +20,14 @@
 #![rustc_partition_reused(module="krate_inlined-x", cfg="rpass2")]
 
 fn main() {
+    x::method();
+
     #[cfg(rpass2)]
     ()
 }
 
 mod x {
-    fn method() {
+    pub fn method() {
         // use some methods that require inlining HIR from another crate:
         let mut v = vec![];
         v.push(1);
diff --git a/src/test/incremental/remove_source_file/main.rs b/src/test/incremental/remove_source_file/main.rs
index 4ba33f3bb3d..3ae26c6aa45 100644
--- a/src/test/incremental/remove_source_file/main.rs
+++ b/src/test/incremental/remove_source_file/main.rs
@@ -11,21 +11,24 @@
 // This test case makes sure that the compiler doesn't crash due to a failing
 // table lookup when a source file is removed.
 
-// revisions:rpass1 rpass2
+// revisions:cfail1 cfail2
 
 // Note that we specify -g so that the FileMaps actually get referenced by the
 // incr. comp. cache:
 // compile-flags: -Z query-dep-graph -g
+// must-compile-successfully
 
-#[cfg(rpass1)]
+#![crate_type= "rlib"]
+
+#[cfg(cfail1)]
 mod auxiliary;
 
-#[cfg(rpass1)]
-fn main() {
+#[cfg(cfail1)]
+pub fn foo() {
     auxiliary::print_hello();
 }
 
-#[cfg(rpass2)]
-fn main() {
+#[cfg(cfail2)]
+pub fn foo() {
     println!("hello");
 }
diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs
index 7d8e6c9d9d7..e1369d92c5c 100644
--- a/src/test/incremental/spans_in_type_debuginfo.rs
+++ b/src/test/incremental/spans_in_type_debuginfo.rs
@@ -14,7 +14,6 @@
 // revisions:rpass1 rpass2
 // compile-flags: -Z query-dep-graph -g
 
-#![rustc_partition_reused(module="spans_in_type_debuginfo", cfg="rpass2")]
 #![rustc_partition_reused(module="spans_in_type_debuginfo-structs", cfg="rpass2")]
 #![rustc_partition_reused(module="spans_in_type_debuginfo-enums", cfg="rpass2")]
 
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index 760975b292f..3e75fa985ac 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -8,47 +8,48 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: rpass1 rpass2
+// revisions: cfail1 cfail2
 // compile-flags: -Z query-dep-graph
+// must-compile-successfully
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
+#![crate_type = "rlib"]
 
 // Here the only thing which changes is the string constant in `x`.
 // Therefore, the compiler deduces (correctly) that typeck is not
 // needed even for callers of `x`.
 
-fn main() { }
 
-mod x {
-    #[cfg(rpass1)]
+pub mod x {
+    #[cfg(cfail1)]
     pub fn x() {
         println!("{}", "1");
     }
 
-    #[cfg(rpass2)]
-    #[rustc_dirty(label="HirBody", cfg="rpass2")]
-    #[rustc_dirty(label="MirOptimized", cfg="rpass2")]
+    #[cfg(cfail2)]
+    #[rustc_dirty(label="HirBody", cfg="cfail2")]
+    #[rustc_dirty(label="MirOptimized", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
     }
 }
 
-mod y {
+pub mod y {
     use x;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
-    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
     pub fn y() {
         x::x();
     }
 }
 
-mod z {
+pub mod z {
     use y;
 
-    #[rustc_clean(label="TypeckTables", cfg="rpass2")]
-    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
+    #[rustc_clean(label="TypeckTables", cfg="cfail2")]
+    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
     pub fn z() {
         y::y();
     }
diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs
new file mode 100644
index 00000000000..bf66ac7829c
--- /dev/null
+++ b/src/test/incremental/warnings-reemitted.rs
@@ -0,0 +1,19 @@
+// 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.
+
+// revisions: cfail1 cfail2 cfail3
+// compile-flags: -Coverflow-checks=on
+// must-compile-successfully
+
+#![allow(warnings)]
+
+fn main() {
+    255u8 + 1; //~ WARNING this expression will panic at run-time
+}
diff --git a/src/test/mir-opt/copy_propagation.rs b/src/test/mir-opt/copy_propagation.rs
index a45e7f21023..69486f46137 100644
--- a/src/test/mir-opt/copy_propagation.rs
+++ b/src/test/mir-opt/copy_propagation.rs
@@ -13,7 +13,10 @@ fn test(x: u32) -> u32 {
     y
 }
 
-fn main() { }
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test(0);
+}
 
 // END RUST SOURCE
 // START rustc.node4.CopyPropagation.before.mir
diff --git a/src/test/mir-opt/deaggregator_test.rs b/src/test/mir-opt/deaggregator_test.rs
index 9fe17a277a7..f4db00dab59 100644
--- a/src/test/mir-opt/deaggregator_test.rs
+++ b/src/test/mir-opt/deaggregator_test.rs
@@ -18,7 +18,10 @@ fn bar(a: usize) -> Baz {
     Baz { x: a, y: 0.0, z: false }
 }
 
-fn main() {}
+fn main() {
+    // Make sure the function actually gets instantiated.
+    bar(0);
+}
 
 // END RUST SOURCE
 // START rustc.node13.Deaggregator.before.mir
diff --git a/src/test/mir-opt/deaggregator_test_enum_2.rs b/src/test/mir-opt/deaggregator_test_enum_2.rs
index 2780f11b9e6..8e7207af0c6 100644
--- a/src/test/mir-opt/deaggregator_test_enum_2.rs
+++ b/src/test/mir-opt/deaggregator_test_enum_2.rs
@@ -23,7 +23,10 @@ fn test1(x: bool, y: i32) -> Foo {
     }
 }
 
-fn main() {}
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test1(false, 0);
+}
 
 // END RUST SOURCE
 // START rustc.node12.Deaggregator.before.mir
diff --git a/src/test/mir-opt/deaggregator_test_multiple.rs b/src/test/mir-opt/deaggregator_test_multiple.rs
index ede3b2e6e29..bc06ab67eaa 100644
--- a/src/test/mir-opt/deaggregator_test_multiple.rs
+++ b/src/test/mir-opt/deaggregator_test_multiple.rs
@@ -19,7 +19,10 @@ fn test(x: i32) -> [Foo; 2] {
     [Foo::A(x), Foo::A(x)]
 }
 
-fn main() { }
+fn main() {
+    // Make sure the function actually gets instantiated.
+    test(0);
+}
 
 // END RUST SOURCE
 // START rustc.node10.Deaggregator.before.mir
diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs
index 1f9ad988acc..61dc1d20659 100644
--- a/src/test/mir-opt/end_region_destruction_extents_1.rs
+++ b/src/test/mir-opt/end_region_destruction_extents_1.rs
@@ -133,11 +133,11 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> {
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         StorageLive(_5);
-//         _5 = promoted1;
+//         _5 = promoted[1];
 //         _4 = &'12ds (*_5);
 //         StorageLive(_7);
 //         StorageLive(_8);
-//         _8 = promoted0;
+//         _8 = promoted[0];
 //         _7 = &'10s (*_8);
 //         _3 = D1<'12ds, '10s>::{{constructor}}(_4, _7);
 //         EndRegion('10s);
diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs
index 384201b7c12..bfac6c739a3 100644
--- a/src/test/mir-opt/issue-41110.rs
+++ b/src/test/mir-opt/issue-41110.rs
@@ -14,6 +14,8 @@ fn main() {
     let x = S.other(S.id());
 }
 
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
 pub fn test() {
     let u = S;
     let mut v = S;
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
new file mode 100644
index 00000000000..56c5dd3be47
--- /dev/null
+++ b/src/test/mir-opt/match_false_edges.rs
@@ -0,0 +1,240 @@
+// Copyright 2012-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: -Z emit-end-regions -Z borrowck-mir
+
+fn guard() -> bool {
+    false
+}
+
+fn guard2(_:i32) -> bool {
+    true
+}
+
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
+pub fn full_tested_match() {
+    let _ = match Some(42) {
+        Some(x) if guard() => (1, x),
+        Some(y) => (2, y),
+        None => (3, 3),
+    };
+}
+
+// no_mangle to make sure this gets instantiated even in an executable.
+#[no_mangle]
+pub fn full_tested_match2() {
+    let _ = match Some(42) {
+        Some(x) if guard() => (1, x),
+        None => (3, 3),
+        Some(y) => (2, y),
+    };
+}
+
+fn main() {
+    let _ = match Some(1) {
+        Some(_w) if guard() => 1,
+        _x => 2,
+        Some(y) if guard2(y) => 3,
+        _z => 4,
+    };
+}
+
+// END RUST SOURCE
+//
+// START rustc.node17.SimplifyBranches-initial.before.mir
+//  bb0: {
+//      ...
+//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _5 = discriminant(_2);
+//      switchInt(_5) -> [0isize: bb5, otherwise: bb3];
+//  }
+//  bb1: { // arm1
+//      StorageLive(_7);
+//      _7 = _3;
+//      _1 = (const 1i32, _7);
+//      StorageDead(_7);
+//      goto -> bb11;
+//  }
+//  bb2: { // binding3(empty) and arm3
+//      _1 = (const 3i32, const 3i32);
+//      goto -> bb11;
+//  }
+//  bb3: {
+//      falseEdges -> [real: bb7, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb10, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      unreachable;
+//  }
+//  bb7: { // binding1 and guard
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_6);
+//      _6 = const guard() -> bb8;
+//  }
+//  bb8: { // end of guard
+//      switchInt(_6) -> [0u8: bb9, otherwise: bb1];
+//  }
+//  bb9: { // to pre_binding2
+//      falseEdges -> [real: bb4, imaginary: bb4];
+//  }
+//  bb10: { // bindingNoLandingPads.before.mir2 and arm2
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = _4;
+//      _1 = (const 2i32, _8);
+//      StorageDead(_8);
+//      goto -> bb11;
+//  }
+//  bb11: {
+//      ...
+//      return;
+//  }
+// END rustc.node17.SimplifyBranches-initial.before.mir
+//
+// START rustc.node42.SimplifyBranches-initial.before.mir
+//  bb0: {
+//      ...
+//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _5 = discriminant(_2);
+//      switchInt(_5) -> [0isize: bb4, otherwise: bb3];
+//  }
+//  bb1: { // arm1
+//      StorageLive(_7);
+//      _7 = _3;
+//      _1 = (const 1i32, _7);
+//      StorageDead(_7);
+//      goto -> bb11;
+//  }
+//  bb2: { // binding3(empty) and arm3
+//      _1 = (const 3i32, const 3i32);
+//      goto -> bb11;
+//  }
+//  bb3: {
+//      falseEdges -> [real: bb7, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb10, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      unreachable;
+//  }
+//  bb7: { // binding1 and guard
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_6);
+//      _6 = const guard() -> bb8;
+//  }
+//  bb8: { // end of guard
+//      switchInt(_6) -> [0u8: bb9, otherwise: bb1];
+//  }
+//  bb9: { // to pre_binding2
+//      falseEdges -> [real: bb5, imaginary: bb4];
+//  }
+//  bb10: { // binding2 and arm2
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = _4;
+//      _1 = (const 2i32, _8);
+//      StorageDead(_8);
+//      goto -> bb11;
+//  }
+//  bb11: {
+//      ...
+//      return;
+//  }
+// END rustc.node42.SimplifyBranches-initial.before.mir
+//
+// START rustc.node67.SimplifyBranches-initial.before.mir
+// bb0: {
+//     ...
+//     _2 = std::option::Option<i32>::Some(const 1i32,);
+//     _7 = discriminant(_2);
+//     switchInt(_7) -> [1isize: bb3, otherwise: bb4];
+// }
+// bb1: { // arm1
+//      _1 = const 1i32;
+//      goto -> bb16;
+// }
+// bb2: { // arm3
+//     _1 = const 3i32;
+//      goto -> bb16;
+// }
+//
+//  bb3: {
+//      falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb11, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      falseEdges -> [real: bb15, imaginary: bb7]; //pre_binding4
+//  }
+//  bb7: {
+//      unreachable;
+//  }
+//  bb8: { // binding1: Some(w) if guard()
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = const guard() -> bb9;
+//  }
+//  bb9: { //end of guard
+//      switchInt(_8) -> [0u8: bb10, otherwise: bb1];
+//  }
+//  bb10: { // to pre_binding2
+//      falseEdges -> [real: bb4, imaginary: bb4];
+//  }
+//  bb11: { // binding2 & arm2
+//      StorageLive(_4);
+//      _4 = _2;
+//      _1 = const 2i32;
+//      goto -> bb16;
+//  }
+//  bb12: { // binding3: Some(y) if guard2(y)
+//      StorageLive(_5);
+//      _5 = ((_2 as Some).0: i32);
+//      StorageLive(_10);
+//      StorageLive(_11);
+//      _11 = _5;
+//      _10 = const guard2(_11) -> bb13;
+//  }
+//  bb13: { // end of guard2
+//      StorageDead(_11);
+//      switchInt(_10) -> [0u8: bb14, otherwise: bb2];
+//  }
+//  bb14: { // to pre_binding4
+//      falseEdges -> [real: bb6, imaginary: bb6];
+//  }
+//  bb15: { // binding4 & arm4
+//      StorageLive(_6);
+//      _6 = _2;
+//      _1 = const 4i32;
+//      goto -> bb16;
+//  }
+// bb16: {
+//     ...
+//     return;
+// }
+// END rustc.node67.SimplifyBranches-initial.before.mir
diff --git a/src/test/mir-opt/nll/liveness-call-subtlety.rs b/src/test/mir-opt/nll/liveness-call-subtlety.rs
new file mode 100644
index 00000000000..873431505f5
--- /dev/null
+++ b/src/test/mir-opt/nll/liveness-call-subtlety.rs
@@ -0,0 +1,51 @@
+// Copyright 2012-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
+
+fn can_panic() -> Box<usize> {
+    Box::new(44)
+}
+
+fn main() {
+    let mut x = Box::new(22);
+    x = can_panic();
+}
+
+// Check that:
+// - `_1` is the variable corresponding to `x`
+// and
+// - `_1` is live when `can_panic` is called (because it may be dropped)
+//
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+//    | Live variables on entry to bb0: []
+//    bb0: {
+//            | Live variables at bb0[0]: []
+//        StorageLive(_1);
+//            | Live variables at bb0[1]: []
+//        StorageLive(_2);
+//            | Live variables at bb0[2]: []
+//        _2 = const 22usize;
+//            | Live variables at bb0[3]: [_2]
+//        _1 = const <std::boxed::Box<T>>::new(_2) -> bb1;
+//    }
+// END rustc.node12.nll.0.mir
+// START rustc.node12.nll.0.mir
+//    | Live variables on entry to bb1: [_1 (drop)]
+//    bb1: {
+//            | Live variables at bb1[0]: [_1 (drop)]
+//        StorageDead(_2);
+//            | Live variables at bb1[1]: [_1 (drop)]
+//        StorageLive(_3);
+//            | Live variables at bb1[2]: [_1 (drop)]
+//        _3 = const can_panic() -> [return: bb2, unwind: bb4];
+//    }
+// END rustc.node12.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
new file mode 100644
index 00000000000..96fd29dfe2f
--- /dev/null
+++ b/src/test/mir-opt/nll/liveness-drop-intra-block.rs
@@ -0,0 +1,41 @@
+// Copyright 2012-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
+
+#![allow(warnings)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut x = 22;
+    loop {
+        // Key point: `x` not live on entry to this basic block.
+        x = 55;
+        if use_x(x) { break; }
+    }
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+//    | Live variables on entry to bb1: []
+//    bb1: {
+//            | Live variables at bb1[0]: []
+//        _1 = const 55usize;
+//            | Live variables at bb1[1]: [_1]
+//        StorageLive(_3);
+//            | Live variables at bb1[2]: [_1]
+//        StorageLive(_4);
+//            | Live variables at bb1[3]: [_1]
+//        _4 = _1;
+//            | Live variables at bb1[4]: [_4]
+//        _3 = const use_x(_4) -> bb2;
+//    }
+// END rustc.node12.nll.0.mir
diff --git a/src/test/mir-opt/nll/liveness-interblock.rs b/src/test/mir-opt/nll/liveness-interblock.rs
new file mode 100644
index 00000000000..c557763c004
--- /dev/null
+++ b/src/test/mir-opt/nll/liveness-interblock.rs
@@ -0,0 +1,50 @@
+// Copyright 2012-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
+
+fn cond() -> bool { false }
+
+fn make_live(_: usize) { }
+
+fn make_dead() { }
+
+fn main() {
+    let x = 5;
+
+    if cond() {
+        make_live(x);
+    } else {
+        // x should be dead on entry to this block
+        make_dead();
+    }
+}
+
+// END RUST SOURCE
+// START rustc.node18.nll.0.mir
+//     | Live variables on entry to bb2: [_1]
+//     bb2: {
+//             | Live variables at bb2[0]: [_1]
+//         StorageLive(_4);
+//             | Live variables at bb2[1]: [_1]
+//         _4 = _1;
+//             | Live variables at bb2[2]: [_4]
+//         _3 = const make_live(_4) -> bb4;
+//     }
+// END rustc.node18.nll.0.mir
+// START rustc.node18.nll.0.mir
+//     | Live variables on entry to bb3: []
+//     bb3: {
+//             | Live variables at bb3[0]: []
+//         _5 = const make_dead() -> bb5;
+//     }
+// END rustc.node18.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
new file mode 100644
index 00000000000..c4f3a6fea53
--- /dev/null
+++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs
@@ -0,0 +1,34 @@
+// Copyright 2012-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 named lifetime translation. Check that we
+// instantiate the types that appear in function arguments with
+// suitable variables and that we setup the outlives relationship
+// between R0 and R1 properly.
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+// ignore-tidy-linelength
+
+#![allow(warnings)]
+
+fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { true }
+
+fn main() {
+}
+
+// END RUST SOURCE
+// START rustc.node4.nll.0.mir
+// | '_#0r: {bb0[0], bb0[1], '_#0r}
+// | '_#1r: {bb0[0], bb0[1], '_#0r, '_#1r}
+// | '_#2r: {bb0[0], bb0[1], '_#2r}
+// ...
+// fn use_x(_1: &'_#0r mut i32, _2: &'_#1r u32, _3: &'_#0r u32, _4: &'_#2r u32) -> bool {
+// END rustc.node4.nll.0.mir
diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs
new file mode 100644
index 00000000000..60a4da430b9
--- /dev/null
+++ b/src/test/mir-opt/nll/reborrow-basic.rs
@@ -0,0 +1,39 @@
+// Copyright 2012-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 reborrow constraints: the region (`R5`) that appears
+// in the type of `r_a` must outlive the region (`R7`) that appears in
+// the type of `r_b`
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: &mut i32) -> bool { true }
+
+fn main() {
+    let mut foo: i32     = 22;
+    let r_a: &mut i32 = &mut foo;
+    let r_b: &mut i32 = &mut *r_a;
+    use_x(r_b);
+}
+
+// END RUST SOURCE
+// START rustc.node13.nll.0.mir
+// | '_#5r: {bb0[6], bb0[7], bb0[8], bb0[9], bb0[10], bb0[11], bb0[12], bb0[13], bb0[14]}
+// ...
+// | '_#7r: {bb0[11], bb0[12], bb0[13], bb0[14]}
+// END rustc.node13.nll.0.mir
+// START rustc.node13.nll.0.mir
+// let _2: &'_#5r mut i32;
+// ...
+// let _4: &'_#7r mut i32;
+// END rustc.node13.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs
new file mode 100644
index 00000000000..7792f0a36f3
--- /dev/null
+++ b/src/test/mir-opt/nll/region-liveness-basic.rs
@@ -0,0 +1,56 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p = &v[0];
+    if true {
+        use_x(*p);
+    } else {
+        use_x(22);
+    }
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+// | '_#0r: {bb1[1], bb2[0], bb2[1]}
+// | '_#1r: {bb1[1], bb2[0], bb2[1]}
+// ...
+//             let _2: &'_#1r usize;
+// END rustc.node12.nll.0.mir
+// START rustc.node12.nll.0.mir
+//    bb1: {
+//            | Live variables at bb1[0]: [_1, _3]
+//        _2 = &'_#0r _1[_3];
+//            | Live variables at bb1[1]: [_2]
+//        switchInt(const true) -> [0u8: bb3, otherwise: bb2];
+//    }
+// END rustc.node12.nll.0.mir
+// START rustc.node12.nll.0.mir
+//    bb2: {
+//            | Live variables at bb2[0]: [_2]
+//        StorageLive(_7);
+//            | Live variables at bb2[1]: [_2]
+//        _7 = (*_2);
+//            | Live variables at bb2[2]: [_7]
+//        _6 = const use_x(_7) -> bb4;
+//    }
+// END rustc.node12.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
new file mode 100644
index 00000000000..4f4bb596e5f
--- /dev/null
+++ b/src/test/mir-opt/nll/region-liveness-drop-may-dangle.rs
@@ -0,0 +1,48 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+#![feature(dropck_eyepatch)]
+#![feature(generic_param_attrs)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p: Wrap<& /* R4 */ usize> = Wrap { value: &v[0] };
+    if true {
+        use_x(*p.value);
+    } else {
+        use_x(22);
+    }
+
+    // `p` will get dropped here. However, because of the
+    // `#[may_dangle]` attribute, we do not need to consider R4 live.
+}
+
+struct Wrap<T> {
+    value: T
+}
+
+unsafe impl<#[may_dangle] T> Drop for Wrap<T> {
+    fn drop(&mut self) { }
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+// | '_#4r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1]}
+// END rustc.node12.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
new file mode 100644
index 00000000000..0ddb745b61f
--- /dev/null
+++ b/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs
@@ -0,0 +1,50 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// ignore-tidy-linelength
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p: Wrap<& /* R1 */ usize> = Wrap { value: &v[0] };
+    if true {
+        use_x(*p.value);
+    } else {
+        use_x(22);
+    }
+
+    // `p` will get dropped here. Because the `#[may_dangle]`
+    // attribute is not present on `Wrap`, we must conservatively
+    // assume that the dtor may access the `value` field, and hence we
+    // must consider R1 to be live.
+}
+
+struct Wrap<T> {
+    value: T
+}
+
+// Look ma, no `#[may_dangle]` attribute here.
+impl<T> Drop for Wrap<T> {
+    fn drop(&mut self) { }
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+// | '_#4r: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1], bb2[2], bb3[0], bb3[1], bb3[2], bb4[0], bb4[1], bb4[2], bb6[0], bb7[0], bb7[1], bb7[2], bb8[0]}
+// END rustc.node12.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
new file mode 100644
index 00000000000..664298b9374
--- /dev/null
+++ b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs
@@ -0,0 +1,49 @@
+// Copyright 2012-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 for the subregion constraints. In this case, the region R3 on
+// `p` includes two disjoint regions of the control-flow graph. The
+// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3,
+// but only at a particular point, and hence they wind up including
+// distinct regions.
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let mut p = &v[0];
+    if true {
+        use_x(*p);
+    } else {
+        use_x(22);
+    }
+
+    p = &v[1];
+    use_x(*p);
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+// | '_#0r: {bb1[1], bb2[0], bb2[1]}
+// ...
+// | '_#2r: {bb7[2], bb7[3], bb7[4]}
+// | '_#3r: {bb1[1], bb2[0], bb2[1], bb7[2], bb7[3], bb7[4]}
+// ...
+// let mut _2: &'_#3r usize;
+// ...
+// _2 = &'_#0r _1[_3];
+// ...
+// _2 = &'_#2r (*_11);
+// END rustc.node12.nll.0.mir
diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs
new file mode 100644
index 00000000000..4ae891f5b70
--- /dev/null
+++ b/src/test/mir-opt/nll/region-subtyping-basic.rs
@@ -0,0 +1,49 @@
+// Copyright 2012-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 liveness constraints: the region (`R1`) that appears
+// in the type of `p` includes the points after `&v[0]` up to (but not
+// including) the call to `use_x`. The `else` branch is not included.
+
+// compile-flags:-Znll -Zverbose
+//                     ^^^^^^^^^ force compiler to dump more region information
+
+#![allow(warnings)]
+
+fn use_x(_: usize) -> bool { true }
+
+fn main() {
+    let mut v = [1, 2, 3];
+    let p = &v[0];
+    let q = p;
+    if true {
+        use_x(*q);
+    } else {
+        use_x(22);
+    }
+}
+
+// END RUST SOURCE
+// START rustc.node12.nll.0.mir
+// | '_#0r: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
+// | '_#1r: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
+// | '_#2r: {bb1[5], bb1[6], bb2[0], bb2[1]}
+// END rustc.node12.nll.0.mir
+// START rustc.node12.nll.0.mir
+// let _2: &'_#1r usize;
+// ...
+// let _6: &'_#2r usize;
+// ...
+// _2 = &'_#0r _1[_3];
+// ...
+// _7 = _2;
+// ...
+// _6 = _7;
+// END rustc.node12.nll.0.mir
diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs
index 53454c0cc9a..a97ce4e8cbe 100644
--- a/src/test/mir-opt/validate_1.rs
+++ b/src/test/mir-opt/validate_1.rs
@@ -62,7 +62,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_2): i32]);
 //         _3 = &ReErased (*_2);
diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs
index 042edca82a6..3585ac0b8be 100644
--- a/src/test/mir-opt/validate_4.rs
+++ b/src/test/mir-opt/validate_4.rs
@@ -78,8 +78,8 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
-//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         ...
 //         _0 = const write_42(_3) -> bb1;
diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs
index fc849c5aee3..ae09d72942e 100644
--- a/src/test/mir-opt/validate_5.rs
+++ b/src/test/mir-opt/validate_5.rs
@@ -49,7 +49,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]);
diff --git a/src/test/parse-fail/issue-33413.rs b/src/test/parse-fail/issue-33413.rs
index 699af8ca7ab..25ae7b4c55a 100644
--- a/src/test/parse-fail/issue-33413.rs
+++ b/src/test/parse-fail/issue-33413.rs
@@ -12,5 +12,4 @@
 
 impl S {
     fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*`
-    //~^ ERROR expected one of `)`, `-`, `box`, `false`, `mut`, `ref`, or `true`, found `*`
 }
diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/auto-trait.rs
index a5246b9300c..842af49e8a7 100644
--- a/src/test/pretty/default-trait-impl.rs
+++ b/src/test/pretty/auto-trait.rs
@@ -12,8 +12,8 @@
 
 // pp-exact
 
-trait MyTrait { }
+auto trait MyTrait { }
 
-impl MyTrait for .. { }
+unsafe auto trait UnsafeMyTrait { }
 
 pub fn main() { }
diff --git a/src/test/pretty/cast-lt.pp b/src/test/pretty/cast-lt.pp
new file mode 100644
index 00000000000..b21158abfe5
--- /dev/null
+++ b/src/test/pretty/cast-lt.pp
@@ -0,0 +1,24 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use std::prelude::v1::*;
+#[macro_use]
+extern crate std as std;
+// 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.
+
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:cast-lt.pp
+
+macro_rules! negative(( $ e : expr ) => { $ e < 0 });
+
+fn main() { (1 as i32) < 0; }
+
diff --git a/src/test/pretty/cast-lt.rs b/src/test/pretty/cast-lt.rs
new file mode 100644
index 00000000000..87b5274545f
--- /dev/null
+++ b/src/test/pretty/cast-lt.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:cast-lt.pp
+
+macro_rules! negative {
+      ($e:expr) => { $e < 0 }
+}
+
+fn main() {
+      negative!(1 as i32);
+}
+
diff --git a/src/test/run-make/cdylib-fewer-symbols/Makefile b/src/test/run-make/cdylib-fewer-symbols/Makefile
new file mode 100644
index 00000000000..954ee792460
--- /dev/null
+++ b/src/test/run-make/cdylib-fewer-symbols/Makefile
@@ -0,0 +1,17 @@
+# Test that allocator-related symbols don't show up as exported from a cdylib as
+# they're internal to Rust and not part of the public ABI.
+
+-include ../tools.mk
+
+ifdef IS_MSVC
+all:
+	true
+else
+all:
+	$(RUSTC) foo.rs
+	nm -g "$(call DYLIB,foo)"
+	nm -g "$(call DYLIB,foo)" | grep -vq __rdl_
+	nm -g "$(call DYLIB,foo)" | grep -vq __rde_
+	nm -g "$(call DYLIB,foo)" | grep -vq __rg_
+	nm -g "$(call DYLIB,foo)" | grep -vq __rust_
+endif
diff --git a/src/test/run-make/cdylib-fewer-symbols/foo.rs b/src/test/run-make/cdylib-fewer-symbols/foo.rs
new file mode 100644
index 00000000000..4ec8d4ee860
--- /dev/null
+++ b/src/test/run-make/cdylib-fewer-symbols/foo.rs
@@ -0,0 +1,16 @@
+// 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.
+
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+pub extern fn foo() -> u32 {
+    3
+}
diff --git a/src/test/run-make/extra-filename-with-temp-outputs/Makefile b/src/test/run-make/extra-filename-with-temp-outputs/Makefile
index 13ca397eaf2..6de4f97df0c 100644
--- a/src/test/run-make/extra-filename-with-temp-outputs/Makefile
+++ b/src/test/run-make/extra-filename-with-temp-outputs/Makefile
@@ -2,5 +2,5 @@
 
 all:
 	$(RUSTC) -C extra-filename=bar foo.rs -C save-temps
-	rm $(TMPDIR)/foobar.foo0.rust-cgu.o
+	rm $(TMPDIR)/foobar.foo0.rcgu.o
 	rm $(TMPDIR)/$(call BIN,foobar)
diff --git a/src/test/run-make/issue-7349/foo.rs b/src/test/run-make/issue-7349/foo.rs
index 6c39b33be08..b75c82afb53 100644
--- a/src/test/run-make/issue-7349/foo.rs
+++ b/src/test/run-make/issue-7349/foo.rs
@@ -13,6 +13,7 @@ fn outer<T>() {
     fn inner() -> u32 {
         8675309
     }
+    inner();
 }
 
 extern "C" fn outer_foreign<T>() {
@@ -20,6 +21,7 @@ extern "C" fn outer_foreign<T>() {
     fn inner() -> u32 {
         11235813
     }
+    inner();
 }
 
 fn main() {
diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs
index 5cb363ac344..834a7554a55 100644
--- a/src/test/run-make/save-analysis/foo.rs
+++ b/src/test/run-make/save-analysis/foo.rs
@@ -441,6 +441,11 @@ fn test_format_args() {
     print!("x is {}, y is {1}, name is {n}", x, y, n = name);
 }
 
+
+union TestUnion {
+    f1: u32
+}
+
 struct FrameBuffer;
 
 struct SilenceGenerator;
diff --git a/src/test/run-make/sepcomp-separate/foo.rs b/src/test/run-make/sepcomp-separate/foo.rs
index bfa2162e27d..64a76e9e0ed 100644
--- a/src/test/run-make/sepcomp-separate/foo.rs
+++ b/src/test/run-make/sepcomp-separate/foo.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+
+
 fn magic_fn() -> usize {
     1234
 }
@@ -24,4 +26,8 @@ mod b {
     }
 }
 
-fn main() { }
+fn main() {
+    magic_fn();
+    a::magic_fn();
+    b::magic_fn();
+}
diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs
index 8ab8f471575..185476fb704 100644
--- a/src/test/run-make/simd-ffi/simd.rs
+++ b/src/test/run-make/simd-ffi/simd.rs
@@ -81,4 +81,5 @@ pub mod marker {
 
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(auto_impl)]
 impl Freeze for .. {}
diff --git a/src/test/run-make/symbols-are-reasonable/lib.rs b/src/test/run-make/symbols-are-reasonable/lib.rs
index ff56ed62869..b9285b24cd6 100644
--- a/src/test/run-make/symbols-are-reasonable/lib.rs
+++ b/src/test/run-make/symbols-are-reasonable/lib.rs
@@ -14,7 +14,8 @@ pub static Y: &'static [u8] = include_bytes!("lib.rs");
 trait Foo { fn dummy(&self) { } }
 impl Foo for usize {}
 
-pub fn dummy() {
+#[no_mangle]
+pub extern "C" fn dummy() {
     // force the vtable to be created
     let _x = &1usize as &Foo;
 }
diff --git a/src/test/run-make/symbols-include-type-name/lib.rs b/src/test/run-make/symbols-include-type-name/lib.rs
index 1c478ed2598..d84f1617db5 100644
--- a/src/test/run-make/symbols-include-type-name/lib.rs
+++ b/src/test/run-make/symbols-include-type-name/lib.rs
@@ -17,3 +17,8 @@ impl Def {
         Def { id: id }
     }
 }
+
+#[no_mangle]
+pub fn user() {
+    let _ = Def::new(0);
+}
diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs
index af24c3b460b..a0feb727028 100644
--- a/src/test/run-make/target-specs/foo.rs
+++ b/src/test/run-make/target-specs/foo.rs
@@ -19,6 +19,7 @@ trait Sized { }
 
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang="start"]
diff --git a/src/test/run-pass/auto-is-contextual.rs b/src/test/run-pass/auto-is-contextual.rs
new file mode 100644
index 00000000000..ad433cc26a7
--- /dev/null
+++ b/src/test/run-pass/auto-is-contextual.rs
@@ -0,0 +1,24 @@
+// 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.
+
+macro_rules! auto {
+    () => (struct S;)
+}
+
+auto!();
+
+fn auto() {}
+
+fn main() {
+    auto();
+    let auto = 10;
+    auto;
+    auto as u8;
+}
diff --git a/src/test/run-pass/auto-traits.rs b/src/test/run-pass/auto-traits.rs
new file mode 100644
index 00000000000..752f5a11375
--- /dev/null
+++ b/src/test/run-pass/auto-traits.rs
@@ -0,0 +1,36 @@
+// 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(optin_builtin_traits)]
+
+auto trait Auto {}
+// Redundant but accepted until we remove it.
+#[allow(auto_impl)]
+impl Auto for .. {}
+
+unsafe auto trait AutoUnsafe {}
+
+impl !Auto for bool {}
+impl !AutoUnsafe for bool {}
+
+struct AutoBool(bool);
+
+impl Auto for AutoBool {}
+unsafe impl AutoUnsafe for AutoBool {}
+
+fn take_auto<T: Auto>(_: T) {}
+fn take_auto_unsafe<T: AutoUnsafe>(_: T) {}
+
+fn main() {
+    take_auto(0);
+    take_auto(AutoBool(true));
+    take_auto_unsafe(0);
+    take_auto_unsafe(AutoBool(true));
+}
diff --git a/src/test/run-pass/closure-expected-type/README.md b/src/test/run-pass/closure-expected-type/README.md
new file mode 100644
index 00000000000..fd493e1ff37
--- /dev/null
+++ b/src/test/run-pass/closure-expected-type/README.md
@@ -0,0 +1,8 @@
+Some tests targeted at how we deduce the types of closure arguments.
+This process is a result of some heuristics aimed at combining the
+*expected type* we have with the *actual types* that we get from
+inputs. This investigation was kicked off by #38714, which revealed
+some pretty deep flaws in the ad-hoc way that we were doing things
+before.
+
+See also `src/test/compile-fail/closure-expected-type`.
diff --git a/src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs b/src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs
new file mode 100644
index 00000000000..8a90a491f7e
--- /dev/null
+++ b/src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs
@@ -0,0 +1,26 @@
+// 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.
+
+fn with_closure<A, F>(_: F)
+    where F: FnOnce(Vec<A>, A)
+{
+}
+
+fn expect_free_supply_free<'x>(x: &'x u32) {
+    with_closure(|mut x: Vec<_>, y| {
+        // Shows that the call to `x.push()` is influencing type of `y`...
+        x.push(22_u32);
+
+        // ...since we now know the type of `y` and can resolve the method call.
+        y.wrapping_add(1);
+    });
+}
+
+fn main() { }
diff --git a/src/test/run-pass/closure-expected-type/issue-38714.rs b/src/test/run-pass/closure-expected-type/issue-38714.rs
new file mode 100644
index 00000000000..a1d512105c9
--- /dev/null
+++ b/src/test/run-pass/closure-expected-type/issue-38714.rs
@@ -0,0 +1,26 @@
+// 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.
+
+struct UsizeRef<'a> {
+    a: &'a usize
+}
+
+type RefTo = Box<for<'r> Fn(&'r Vec<usize>) -> UsizeRef<'r>>;
+
+fn ref_to<'a>(vec: &'a Vec<usize>) -> UsizeRef<'a> {
+    UsizeRef{ a: &vec[0]}
+}
+
+fn main() {
+    // Regression test: this was causing ICEs; it should compile.
+    let a: RefTo = Box::new(|vec: &Vec<usize>| {
+        UsizeRef{ a: &vec[0] }
+    });
+}
diff --git a/src/test/run-pass/closure-expected-type/supply-just-return-type.rs b/src/test/run-pass/closure-expected-type/supply-just-return-type.rs
new file mode 100644
index 00000000000..0b930b338fd
--- /dev/null
+++ b/src/test/run-pass/closure-expected-type/supply-just-return-type.rs
@@ -0,0 +1,35 @@
+// 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.
+
+fn with_closure<F, R>(f: F) -> Result<char, R>
+    where F: FnOnce(&char) -> Result<char, R>,
+{
+    f(&'a')
+}
+
+fn main() {
+    // Test that supplying the `-> Result<char, ()>` manually here
+    // (which is needed to constrain `R`) still allows us to figure
+    // out that the type of `x` is `&'a char` where `'a` is bound in
+    // the closure (if we didn't, we'd get a type-error because
+    // `with_closure` requires a bound region).
+    //
+    // This pattern was found in the wild.
+    let z = with_closure(|x| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+
+    // It also works with `_`:
+    let z = with_closure(|x: _| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+
+    // It also works with `&_`:
+    let z = with_closure(|x: &_| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+}
diff --git a/src/test/run-pass/closure-expected-type/supply-nothing.rs b/src/test/run-pass/closure-expected-type/supply-nothing.rs
new file mode 100644
index 00000000000..15d8b393c15
--- /dev/null
+++ b/src/test/run-pass/closure-expected-type/supply-nothing.rs
@@ -0,0 +1,20 @@
+// 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.
+
+fn with_closure<F>(f: F) -> u32
+    where F: FnOnce(&u32, &u32) -> u32
+{
+    f(&22, &44)
+}
+
+fn main() {
+    let z = with_closure(|x, y| x + y).wrapping_add(1);
+    assert_eq!(z, 22 + 44 + 1);
+}
diff --git a/src/test/run-pass/issue-29516.rs b/src/test/run-pass/issue-29516.rs
index b586abc29e2..5fa0a002a10 100644
--- a/src/test/run-pass/issue-29516.rs
+++ b/src/test/run-pass/issue-29516.rs
@@ -11,6 +11,7 @@
 #![feature(optin_builtin_traits)]
 
 trait NotSame {}
+#[allow(auto_impl)]
 impl NotSame for .. {}
 impl<A> !NotSame for (A, A) {}
 
diff --git a/src/test/run-pass/issue-45731.rs b/src/test/run-pass/issue-45731.rs
new file mode 100644
index 00000000000..ec35035dab4
--- /dev/null
+++ b/src/test/run-pass/issue-45731.rs
@@ -0,0 +1,34 @@
+// 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.
+
+// compile-flags:--test -g
+
+use std::{env, panic, fs};
+
+#[cfg(target_os = "macos")]
+#[test]
+fn simple_test() {
+    // Find our dSYM and replace the DWARF binary with an empty file
+    let mut dsym_path = env::current_exe().unwrap();
+    let executable_name = dsym_path.file_name().unwrap().to_str().unwrap().to_string();
+    assert!(dsym_path.pop()); // Pop executable
+    dsym_path.push(format!("{}.dSYM/Contents/Resources/DWARF/{0}", executable_name));
+    {
+        let file = fs::OpenOptions::new().read(false).write(true).truncate(true).create(false)
+            .open(&dsym_path).unwrap();
+    }
+
+    env::set_var("RUST_BACKTRACE", "1");
+
+    // We don't need to die of panic, just trigger a backtrace
+    let _ = panic::catch_unwind(|| {
+        assert!(false);
+    });
+}
diff --git a/src/test/run-pass/mir-inlining/ice-issue-45493.rs b/src/test/run-pass/mir-inlining/ice-issue-45493.rs
new file mode 100644
index 00000000000..bd178f0e5bd
--- /dev/null
+++ b/src/test/run-pass/mir-inlining/ice-issue-45493.rs
@@ -0,0 +1,26 @@
+// 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.
+
+// compile-flags:-Zmir-opt-level=2
+
+trait Array {
+    type Item;
+}
+
+fn foo<A: Array>() {
+    let _: *mut A::Item = std::ptr::null_mut();
+}
+
+struct Foo;
+impl Array for Foo { type Item = i32; }
+
+fn main() {
+    foo::<Foo>();
+}
diff --git a/src/test/run-pass/next-power-of-two-overflow-debug.rs b/src/test/run-pass/next-power-of-two-overflow-debug.rs
new file mode 100644
index 00000000000..a3e7ffd4e49
--- /dev/null
+++ b/src/test/run-pass/next-power-of-two-overflow-debug.rs
@@ -0,0 +1,36 @@
+// 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.
+
+// compile-flags: -C debug_assertions=yes
+
+#![feature(i128_type)]
+
+use std::panic;
+
+fn main() {
+    macro_rules! overflow_test {
+        ($t:ident) => (
+            let r = panic::catch_unwind(|| {
+                ($t::max_value()).next_power_of_two()
+            });
+            assert!(r.is_err());
+
+            let r = panic::catch_unwind(|| {
+                (($t::max_value() >> 1) + 2).next_power_of_two()
+            });
+            assert!(r.is_err());
+        )
+    }
+    overflow_test!(u8);
+    overflow_test!(u16);
+    overflow_test!(u32);
+    overflow_test!(u64);
+    overflow_test!(u128);
+}
diff --git a/src/test/run-pass/next-power-of-two-overflow-ndebug.rs b/src/test/run-pass/next-power-of-two-overflow-ndebug.rs
new file mode 100644
index 00000000000..f8bcb961c68
--- /dev/null
+++ b/src/test/run-pass/next-power-of-two-overflow-ndebug.rs
@@ -0,0 +1,24 @@
+// 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.
+
+// compile-flags: -C debug_assertions=no
+
+#![feature(i128_type)]
+
+fn main() {
+    for i in 129..256 {
+        assert_eq!((i as u8).next_power_of_two(), 0);
+    }
+
+    assert_eq!(((1u16 << 15) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u32 << 31) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u64 << 63) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u128 << 127) + 1).next_power_of_two(), 0);
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644
index 00000000000..12d1bf9ea91
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -0,0 +1,19 @@
+// Copyright 2012 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644
index 00000000000..a2c6f8c05e2
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -0,0 +1,23 @@
+// Copyright 2012 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(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644
index 00000000000..d04c1073ad9
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs
@@ -0,0 +1,18 @@
+// Copyright 2012 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/enums.rs b/src/test/run-pass/rfc-2008-non-exhaustive/enums.rs
new file mode 100644
index 00000000000..9d41eca8fe5
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/enums.rs
@@ -0,0 +1,33 @@
+// Copyright 2012 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.
+
+// aux-build:enums.rs
+extern crate enums;
+
+// ignore-pretty issue #37199
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => 1,
+        NonExhaustiveEnum::Tuple(_) => 2,
+        // This particular arm tests that a enum marked as non-exhaustive
+        // will not error if its variants are matched exhaustively.
+        NonExhaustiveEnum::Struct { field } => field,
+        _ => 0 // no error with wildcard
+    };
+
+    match enum_unit {
+        _ => "no error with only wildcard"
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs
new file mode 100644
index 00000000000..8f1ba364b0e
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs
@@ -0,0 +1,28 @@
+// Copyright 2012 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(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third",
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/structs.rs b/src/test/run-pass/rfc-2008-non-exhaustive/structs.rs
new file mode 100644
index 00000000000..bb65e10da27
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/structs.rs
@@ -0,0 +1,27 @@
+// Copyright 2012 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.
+
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct};
+
+// We only test matching here as we cannot create non-exhaustive
+// structs from another crate. ie. they'll never pass in run-pass tests.
+
+fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) {
+    let NormalStruct { first_field, second_field, .. } = ns;
+
+    let TupleStruct { 0: first, 1: second, .. } = ts;
+
+    let UnitStruct { .. } = us;
+}
+
+fn main() { }
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs
new file mode 100644
index 00000000000..175782f10fc
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs
@@ -0,0 +1,40 @@
+// Copyright 2012 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(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
+
+fn main() {
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+
+    let NormalStruct { first_field, second_field } = ns;
+
+    let ts = TupleStruct { 0: 340, 1: 480 };
+    let ts_constructor = TupleStruct(340, 480);
+
+    let TupleStruct { 0: first, 1: second } = ts;
+    let TupleStruct(first, second) = ts_constructor;
+
+    let us = UnitStruct {};
+    let us_constructor = UnitStruct;
+
+    let UnitStruct { } = us;
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/variants.rs b/src/test/run-pass/rfc-2008-non-exhaustive/variants.rs
new file mode 100644
index 00000000000..2658c59a699
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/variants.rs
@@ -0,0 +1,31 @@
+// Copyright 2012 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.
+
+// aux-build:variants.rs
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+fn main() {
+    let variant_tuple = NonExhaustiveVariants::Tuple { 0: 340 };
+    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+    match variant_struct {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Struct { field, .. } => "",
+        NonExhaustiveVariants::Tuple(fe_tpl, ..) => ""
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs
new file mode 100644
index 00000000000..a1c376c1798
--- /dev/null
+++ b/src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs
@@ -0,0 +1,34 @@
+// Copyright 2012 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(non_exhaustive)]
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
+
+fn main() {
+    let variant_tuple = NonExhaustiveVariants::Tuple(340);
+    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+    match variant_tuple {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        NonExhaustiveVariants::Struct { field } => ""
+    };
+}
diff --git a/src/test/run-pass/saturating-float-casts.rs b/src/test/run-pass/saturating-float-casts.rs
new file mode 100644
index 00000000000..6db4d7635f0
--- /dev/null
+++ b/src/test/run-pass/saturating-float-casts.rs
@@ -0,0 +1,164 @@
+// 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.
+
+// compile-flags: -Z saturating-float-casts
+
+#![feature(test, i128, i128_type, stmt_expr_attributes)]
+#![deny(overflowing_literals)]
+extern crate test;
+
+use std::{f32, f64};
+use std::{u8, i8, u16, i16, u32, i32, u64, i64};
+#[cfg(not(target_os="emscripten"))]
+use std::{u128, i128};
+use test::black_box;
+
+macro_rules! test {
+    ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => (
+        // black_box disables constant evaluation to test run-time conversions:
+        assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected,
+                    "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+    );
+
+    ($fval:expr, f* -> $ity:ident, $ival:expr) => (
+        test!($fval, f32 -> $ity, $ival);
+        test!($fval, f64 -> $ity, $ival);
+    )
+}
+
+// This macro tests const eval in addition to run-time evaluation.
+// If and when saturating casts are adopted, this macro should be merged with test!() to ensure
+// that run-time and const eval agree on inputs that currently trigger a const eval error.
+macro_rules! test_c {
+    ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ({
+        test!($val, $src_ty -> $dest_ty, $expected);
+        {
+            const X: $src_ty = $val;
+            const Y: $dest_ty = X as $dest_ty;
+            assert_eq!(Y, $expected,
+                        "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+        }
+    });
+
+    ($fval:expr, f* -> $ity:ident, $ival:expr) => (
+        test!($fval, f32 -> $ity, $ival);
+        test!($fval, f64 -> $ity, $ival);
+    )
+}
+
+macro_rules! common_fptoi_tests {
+    ($fty:ident -> $($ity:ident)+) => ({ $(
+        test!($fty::NAN, $fty -> $ity, 0);
+        test!($fty::INFINITY, $fty -> $ity, $ity::MAX);
+        test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN);
+        // These two tests are not solely float->int tests, in particular the latter relies on
+        // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float
+        // as well, the test is just slightly misplaced.
+        test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN);
+        test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX);
+        test_c!(0., $fty -> $ity, 0);
+        test_c!($fty::MIN_POSITIVE, $fty -> $ity, 0);
+        test!(-0.9, $fty -> $ity, 0);
+        test_c!(1., $fty -> $ity, 1);
+        test_c!(42., $fty -> $ity, 42);
+    )+ });
+
+    (f* -> $($ity:ident)+) => ({
+        common_fptoi_tests!(f32 -> $($ity)+);
+        common_fptoi_tests!(f64 -> $($ity)+);
+    })
+}
+
+macro_rules! fptoui_tests {
+    ($fty: ident -> $($ity: ident)+) => ({ $(
+        test!(-0., $fty -> $ity, 0);
+        test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0);
+        test!(-0.99999994, $fty -> $ity, 0);
+        test!(-1., $fty -> $ity, 0);
+        test!(-100., $fty -> $ity, 0);
+        test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0);
+        test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0);
+    )+ });
+
+    (f* -> $($ity:ident)+) => ({
+        fptoui_tests!(f32 -> $($ity)+);
+        fptoui_tests!(f64 -> $($ity)+);
+    })
+}
+
+pub fn main() {
+    common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64);
+    fptoui_tests!(f* -> u8 u16 u32 u64);
+    // FIXME emscripten does not support i128
+    #[cfg(not(target_os="emscripten"))] {
+        common_fptoi_tests!(f* -> i128 u128);
+        fptoui_tests!(f* -> u128);
+    }
+
+    // The following tests cover edge cases for some integer types.
+
+    // # u8
+    test_c!(254., f* -> u8, 254);
+    test!(256., f* -> u8, 255);
+
+    // # i8
+    test_c!(-127., f* -> i8, -127);
+    test!(-129., f* -> i8, -128);
+    test_c!(126., f* -> i8, 126);
+    test!(128., f* -> i8, 127);
+
+    // # i32
+    // -2147483648. is i32::MIN (exactly)
+    test_c!(-2147483648., f* -> i32, i32::MIN);
+    // 2147483648. is i32::MAX rounded up
+    test!(2147483648., f32 -> i32, 2147483647);
+    // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to
+    // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128:
+    test_c!(2147483520., f32 -> i32, 2147483520);
+    // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7
+    test!(-2147483904., f* -> i32, i32::MIN);
+    test_c!(-2147483520., f* -> i32, -2147483520);
+
+    // # u32
+    // round(MAX) and nextUp(round(MAX))
+    test_c!(4294967040., f* -> u32, 4294967040);
+    test!(4294967296., f* -> u32, 4294967295);
+
+    // # u128
+    #[cfg(not(target_os="emscripten"))]
+    {
+        // float->int:
+        test_c!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000);
+        // nextDown(f32::MAX) = 2^128 - 2 * 2^104
+        const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.;
+        test_c!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000);
+
+        // int->float:
+        // f32::MAX - 0.5 ULP and smaller should be rounded down
+        test_c!(0xfffffe00000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+        test_c!(0xfffffe7fffffffffffffffffffffffff, u128 -> f32, SECOND_LARGEST_F32);
+        test_c!(0xfffffe80000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+        // numbers within < 0.5 ULP of f32::MAX it should be rounded to f32::MAX
+        test_c!(0xfffffe80000000000000000000000001, u128 -> f32, f32::MAX);
+        test_c!(0xfffffeffffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+        test_c!(0xffffff00000000000000000000000000, u128 -> f32, f32::MAX);
+        test_c!(0xffffff00000000000000000000000001, u128 -> f32, f32::MAX);
+        test_c!(0xffffff7fffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+        // f32::MAX + 0.5 ULP and greater should be rounded to infinity
+        test_c!(0xffffff80000000000000000000000000, u128 -> f32, f32::INFINITY);
+        test_c!(0xffffff80000000f00000000000000000, u128 -> f32, f32::INFINITY);
+        test_c!(0xffffff87ffffffffffffffff00000001, u128 -> f32, f32::INFINITY);
+
+        // u128->f64 should not be affected by the u128->f32 checks
+        test_c!(0xffffff80000000000000000000000000, u128 -> f64,
+              340282356779733661637539395458142568448.0);
+        test_c!(u128::MAX, u128 -> f64, 340282366920938463463374607431768211455.0);
+    }
+}
diff --git a/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs b/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
index 52bd386ba59..4fd55bd482c 100644
--- a/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
+++ b/src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
@@ -16,6 +16,7 @@ pub mod bar {
 
     pub trait Bar {}
 
+    #[allow(auto_impl)]
     impl Bar for .. {}
 
     pub trait Foo {
diff --git a/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs b/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
index 6e8f80c8f5f..d886778278d 100644
--- a/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
+++ b/src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
@@ -12,4 +12,5 @@
 
 pub trait AnOibit {}
 
+#[allow(auto_impl)]
 impl AnOibit for .. {}
diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs
index 48ef4b6be66..f74f66ce729 100644
--- a/src/test/rustdoc/impl-parts.rs
+++ b/src/test/rustdoc/impl-parts.rs
@@ -12,6 +12,7 @@
 
 pub trait AnOibit {}
 
+#[allow(auto_impl)]
 impl AnOibit for .. {}
 
 pub struct Foo<T> { field: T }
diff --git a/src/test/rustdoc/issue-45584.rs b/src/test/rustdoc/issue-45584.rs
new file mode 100644
index 00000000000..6d6ae3dc94a
--- /dev/null
+++ b/src/test/rustdoc/issue-45584.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.
+
+#![crate_name = "foo"]
+
+pub trait Bar<T, U> {}
+
+// @has 'foo/struct.Foo1.html'
+pub struct Foo1;
+// @count - '//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
+impl Bar<Foo1, &'static Foo1> for Foo1 {}
+
+// @has 'foo/struct.Foo2.html'
+pub struct Foo2;
+// @count - '//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8"
+impl Bar<&'static Foo2, Foo2> for u8 {}
diff --git a/src/test/rustdoc/method-list.rs b/src/test/rustdoc/method-list.rs
new file mode 100644
index 00000000000..b7112885e88
--- /dev/null
+++ b/src/test/rustdoc/method-list.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// ignore-tidy-linelength
+
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="sidebar-links"]/a' 'super_long_name'
+// @has - '//*[@class="sidebar-links"]/a' 'Disp'
+pub struct Foo(usize);
+
+impl Foo {
+    pub fn super_long_name() {}
+}
+
+pub trait Disp {
+    fn disp_trait_method();
+}
+
+impl Disp for Foo {
+    fn disp_trait_method() {}
+}
diff --git a/src/test/rustdoc/playground-arg.rs b/src/test/rustdoc/playground-arg.rs
index f0d55ef6e9f..478477dea61 100644
--- a/src/test/rustdoc/playground-arg.rs
+++ b/src/test/rustdoc/playground-arg.rs
@@ -21,4 +21,4 @@
 pub fn dummy() {}
 
 // ensure that `extern crate foo;` was inserted into code snips automatically:
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=extern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run"
diff --git a/src/test/rustdoc/playground.rs b/src/test/rustdoc/playground.rs
index 9eb8dec51a7..8e193efaf85 100644
--- a/src/test/rustdoc/playground.rs
+++ b/src/test/rustdoc/playground.rs
@@ -34,6 +34,6 @@
 //! }
 //! ```
 
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=fn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D%0A&version=nightly"]' "Run"
diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs
new file mode 100644
index 00000000000..9be40441e9d
--- /dev/null
+++ b/src/test/rustdoc/sidebar-items.rs
@@ -0,0 +1,59 @@
+// 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.
+
+#![crate_name = "foo"]
+
+// @has foo/trait.Foo.html
+// @has - '//*[@class="sidebar-title"][@href="#required-methods"]' 'Required Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+// @has - '//*[@class="sidebar-title"][@href="#provided-methods"]' 'Provided Methods'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-title"][@href="#associated-const"]' 'Associated Constants'
+// @has - '//*[@class="sidebar-links"]/a' 'BAR'
+// @has - '//*[@class="sidebar-title"][@href="#associated-types"]' 'Associated Types'
+// @has - '//*[@class="sidebar-links"]/a' 'Output'
+pub trait Foo {
+    const BAR: u32 = 0;
+    type Output: ?Sized;
+
+    fn foo() {}
+    fn bar() -> Self::Output;
+}
+
+// @has foo/struct.Bar.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f"]' 'f'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.u"]' 'u'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub struct Bar {
+    pub f: u32,
+    pub u: u32,
+    w: u32,
+}
+
+// @has foo/enum.En.html
+// @has - '//*[@class="sidebar-title"][@href="#variants"]' 'Variants'
+// @has - '//*[@class="sidebar-links"]/a' 'foo'
+// @has - '//*[@class="sidebar-links"]/a' 'bar'
+pub enum En {
+    foo,
+    bar,
+}
+
+// @has foo/union.MyUnion.html
+// @has - '//*[@class="sidebar-title"][@href="#fields"]' 'Fields'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f1"]' 'f1'
+// @has - '//*[@class="sidebar-links"]/a[@href="#structfield.f2"]' 'f2'
+// @!has - '//*[@class="sidebar-links"]/a' 'w'
+pub union MyUnion {
+    pub f1: u32,
+    pub f2: f32,
+    w: u32,
+}
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index 0828fd28b58..02a9d7ee0ef 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -2,7 +2,7 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc
   --> $DIR/unicode.rs:11:8
    |
 11 | extern "路濫狼á́́" fn foo() {}
-   |        ^^^^^^^^
+   |        ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/unicode_2.rs b/src/test/ui/codemap_tests/unicode_2.rs
new file mode 100644
index 00000000000..cc3eae90f90
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_2.rs
@@ -0,0 +1,17 @@
+// 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.
+
+#![feature(non_ascii_idents)]
+
+fn main() {
+    let _ = ("a̐éö̲", 0u7);
+    let _ = ("아あ", 1i42);
+    let _ = a̐é;
+}
diff --git a/src/test/ui/codemap_tests/unicode_2.stderr b/src/test/ui/codemap_tests/unicode_2.stderr
new file mode 100644
index 00000000000..6cfa66730a2
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_2.stderr
@@ -0,0 +1,24 @@
+error: invalid width `7` for integer literal
+  --> $DIR/unicode_2.rs:14:25
+   |
+14 |     let _ = ("a̐éö̲", 0u7);
+   |                     ^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error: invalid width `42` for integer literal
+  --> $DIR/unicode_2.rs:15:20
+   |
+15 |     let _ = ("아あ", 1i42);
+   |                      ^^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error[E0425]: cannot find value `a̐é` in this scope
+  --> $DIR/unicode_2.rs:16:13
+   |
+16 |     let _ = a̐é;
+   |             ^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/codemap_tests/unicode_3.rs b/src/test/ui/codemap_tests/unicode_3.rs
new file mode 100644
index 00000000000..5294eedb845
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_3.rs
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+    println!("{}", s);
+}
diff --git a/src/test/ui/codemap_tests/unicode_3.stderr b/src/test/ui/codemap_tests/unicode_3.stderr
new file mode 100644
index 00000000000..a7514a6b792
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode_3.stderr
@@ -0,0 +1,10 @@
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/unicode_3.rs:12:45
+   |
+12 |     let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+   |                       ----------^^^^^^^^^^^
+   |                       |
+   |                       help: use `loop`
+   |
+   = note: #[warn(while_true)] on by default
+
diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr
index 5ad9c19fa8c..3ed3297e05e 100644
--- a/src/test/ui/deref-suggestion.stderr
+++ b/src/test/ui/deref-suggestion.stderr
@@ -10,8 +10,8 @@ error[E0308]: mismatched types
            - .escape_debug()
            - .escape_default()
            - .escape_unicode()
-           - .to_lowercase()
-           - .to_uppercase()
+           - .to_ascii_lowercase()
+           - .to_ascii_uppercase()
 
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:23:10
diff --git a/src/test/ui/issue-35241.rs b/src/test/ui/issue-35241.rs
new file mode 100644
index 00000000000..7ec3974854b
--- /dev/null
+++ b/src/test/ui/issue-35241.rs
@@ -0,0 +1,15 @@
+// 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.
+
+struct Foo(u32);
+
+fn test() -> Foo { Foo }
+
+fn main() {}
diff --git a/src/test/ui/issue-35241.stderr b/src/test/ui/issue-35241.stderr
new file mode 100644
index 00000000000..bb1bba152bb
--- /dev/null
+++ b/src/test/ui/issue-35241.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-35241.rs:13:20
+   |
+13 | fn test() -> Foo { Foo }
+   |              ---   ^^^
+   |              |     |
+   |              |     expected struct `Foo`, found fn item
+   |              |     did you mean `Foo(/* fields */)`?
+   |              expected `Foo` because of return type
+   |
+   = note: expected type `Foo`
+              found type `fn(u32) -> Foo {Foo::{{constructor}}}`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-40782.rs b/src/test/ui/issue-40782.rs
new file mode 100644
index 00000000000..56ee225105f
--- /dev/null
+++ b/src/test/ui/issue-40782.rs
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    for i 0..2 {
+    }
+}
+
diff --git a/src/test/ui/issue-40782.stderr b/src/test/ui/issue-40782.stderr
new file mode 100644
index 00000000000..0d49eebbdbf
--- /dev/null
+++ b/src/test/ui/issue-40782.stderr
@@ -0,0 +1,8 @@
+error: missing `in` in `for` loop
+  --> $DIR/issue-40782.rs:12:10
+   |
+12 |     for i 0..2 {
+   |          ^ help: try adding `in` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-44078.stderr b/src/test/ui/issue-44078.stderr
index 389f3b2479a..2ed4578d538 100644
--- a/src/test/ui/issue-44078.stderr
+++ b/src/test/ui/issue-44078.stderr
@@ -2,7 +2,7 @@ error: unterminated double quote string
   --> $DIR/issue-44078.rs:12:8
    |
 12 |       "😊"";
-   |  ________^
+   |  _________^
 13 | | }
    | |__^
 
diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr
index 9beae91540a..e7afbb574ef 100644
--- a/src/test/ui/issue-44406.stderr
+++ b/src/test/ui/issue-44406.stderr
@@ -13,14 +13,5 @@ error: expected type, found keyword `true`
 18 |     foo!(true);
    |          ^^^^ expecting a type here because of type ascription
 
-error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true`
-  --> $DIR/issue-44406.rs:18:10
-   |
-13 |         bar(baz: $rest)
-   |                 - expected one of 20 possible tokens here
-...
-18 |     foo!(true);
-   |          ^^^^ unexpected token
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-45730.rs b/src/test/ui/issue-45730.rs
new file mode 100644
index 00000000000..f725d69ca65
--- /dev/null
+++ b/src/test/ui/issue-45730.rs
@@ -0,0 +1,19 @@
+// 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.
+
+use std::fmt;
+fn main() {
+    let x: *const _ = 0 as _;
+
+    let x: *const _ = 0 as *const _;
+    let y: Option<*const fmt::Debug> = Some(x) as _;
+
+    let x = 0 as *const i32 as *const _ as *mut _;
+}
diff --git a/src/test/ui/issue-45730.stderr b/src/test/ui/issue-45730.stderr
new file mode 100644
index 00000000000..c4f2e856b7b
--- /dev/null
+++ b/src/test/ui/issue-45730.stderr
@@ -0,0 +1,32 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:13:23
+   |
+13 |     let x: *const _ = 0 as _;
+   |                       ^^^^^-
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:15:23
+   |
+15 |     let x: *const _ = 0 as *const _;
+   |                       ^^^^^--------
+   |                            |
+   |                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error[E0641]: cannot cast to a pointer of an unknown kind
+  --> $DIR/issue-45730.rs:18:13
+   |
+18 |     let x = 0 as *const i32 as *const _ as *mut _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
+   |                                            |
+   |                                            help: consider giving more type information
+   |
+   = note: The type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs
new file mode 100644
index 00000000000..55752f753ef
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.rs
@@ -0,0 +1,30 @@
+// 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.
+
+#[derive(Clone)]
+enum Foo<'a> {
+    Bar(&'a str),
+}
+
+impl<'a> Foo<'a> {
+    fn bar(&self, other: Foo) -> Foo<'a> {
+        match *self {
+            Foo::Bar(s) => {
+                if s == "test" {
+                    other
+                } else {
+                    self.clone()
+                }
+            }
+        }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr
new file mode 100644
index 00000000000..d1660a620b6
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-early-bound-in-struct.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `other`
+  --> $DIR/ex1-return-one-existing-name-early-bound-in-struct.rs:21:21
+   |
+17 |     fn bar(&self, other: Foo) -> Foo<'a> {
+   |                   ----- consider changing the type of `other` to `Foo<'a>`
+...
+21 |                     other
+   |                     ^^^^^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
index 5d182008209..5d182008209 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.rs
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.rs
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr
new file mode 100644
index 00000000000..980f14a51d9
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-early-bound.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `y`
+  --> $DIR/ex2a-push-one-existing-name-early-bound.rs:17:12
+   |
+13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
+   |                                       - consider changing the type of `y` to `&'a T`
+...
+17 |     x.push(y);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr
deleted file mode 100644
index 58f2cb94cec..00000000000
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-earlybound-regions.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-earlybound-regions.rs:17:12
-   |
-13 | fn baz<'a, 'b, T>(x: &mut Vec<&'a T>, y: &T)
-   |                               -----      -- these two types are declared with different lifetimes...
-...
-17 |     x.push(y);
-   |            ^ ...but data from `y` flows into `x` here
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.rs b/src/test/ui/lint/unreachable_pub-pub_crate.rs
new file mode 100644
index 00000000000..b794f6c9517
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.rs
@@ -0,0 +1,74 @@
+// 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.
+
+// This is just like unreachable_pub.rs, but without the
+// `crate_visibility_modifier` feature (so that we can test the suggestions to
+// use `pub(crate)` that are given when that feature is off, as opposed to the
+// suggestions to use `crate` given when it is on). When that feature becomes
+// stable, this test can be deleted.
+
+#![feature(macro_vis_matcher)]
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        pub(crate) electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        pub(crate) fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    pub(crate) struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    pub(crate) struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.stderr b/src/test/ui/lint/unreachable_pub-pub_crate.stderr
new file mode 100644
index 00000000000..84cbf87c1a1
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub-pub_crate.stderr
@@ -0,0 +1,134 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:24:5
+   |
+24 |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub-pub_crate.rs:20:9
+   |
+20 | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:26:5
+   |
+26 |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub-pub_crate.rs:28:9
+   |
+28 |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:34:9
+   |
+34 |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:38:5
+   |
+38 |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:39:5
+   |
+39 |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:40:5
+   |
+40 |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:41:5
+   |
+41 |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:42:5
+   |
+42 |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:43:5
+   |
+43 |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:44:5
+   |
+44 |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:47:47
+   |
+47 |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               -----------^^^^^^^^^^^^^
+   |                                               |
+   |                                               help: consider restricting its visibility: `pub(crate)`
+48 |     }
+49 |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ---------------------------------------------------- in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:52:9
+   |
+52 |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
diff --git a/src/test/ui/lint/unreachable_pub.rs b/src/test/ui/lint/unreachable_pub.rs
new file mode 100644
index 00000000000..5812061dfdb
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub.rs
@@ -0,0 +1,69 @@
+// 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(crate_visibility_modifier)]
+#![feature(macro_vis_matcher)]
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        crate electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        crate fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    crate struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    crate struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr
new file mode 100644
index 00000000000..bdd016ff2df
--- /dev/null
+++ b/src/test/ui/lint/unreachable_pub.stderr
@@ -0,0 +1,134 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:19:5
+   |
+19 |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub.rs:15:9
+   |
+15 | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:21:5
+   |
+21 |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub.rs:23:9
+   |
+23 |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:29:9
+   |
+29 |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:33:5
+   |
+33 |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:34:5
+   |
+34 |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:35:5
+   |
+35 |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:36:5
+   |
+36 |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:37:5
+   |
+37 |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:38:5
+   |
+38 |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:39:5
+   |
+39 |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:42:47
+   |
+42 |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               -----------^^^^^^^^^^^^^
+   |                                               |
+   |                                               help: consider restricting its visibility: `crate`
+43 |     }
+44 |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ---------------------------------------------------- in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:47:9
+   |
+47 |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs
index 15251795d5e..ad501e66809 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.rs
+++ b/src/test/ui/lint/unused_parens_json_suggestion.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
index ae5b53da175..e166f7011b5 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -1 +1,91 @@
-{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"lint level defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":847,"byte_end":860,"line_start":19,"line_end":19,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![warn(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":null}],"rendered":null}
+{
+  "message": "unnecessary parentheses around assigned value",
+  "code": {
+    "code": "unused_parens",
+    "explanation": null
+  },
+  "level": "warning",
+  "spans": [
+    {
+      "file_name": "$DIR/unused_parens_json_suggestion.rs",
+      "byte_start": 1027,
+      "byte_end": 1040,
+      "line_start": 24,
+      "line_end": 24,
+      "column_start": 14,
+      "column_end": 27,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let _a = (1 / (2 + 3));",
+          "highlight_start": 14,
+          "highlight_end": 27
+        }
+      ],
+      "label": null,
+      "suggested_replacement": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "lint level defined here",
+      "code": null,
+      "level": "note",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 873,
+          "byte_end": 886,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 9,
+          "column_end": 22,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "#![warn(unused_parens)]",
+              "highlight_start": 9,
+              "highlight_end": 22
+            }
+          ],
+          "label": null,
+          "suggested_replacement": null,
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    },
+    {
+      "message": "remove these parentheses",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 1027,
+          "byte_end": 1040,
+          "line_start": 24,
+          "line_end": 24,
+          "column_start": 14,
+          "column_end": 27,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "    let _a = (1 / (2 + 3));",
+              "highlight_start": 14,
+              "highlight_end": 27
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "1 / (2 + 3)",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": null
+}
diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs
index 20c24d64050..27232c4fec4 100644
--- a/src/test/ui/lint/use_suggestion_json.rs
+++ b/src/test/ui/lint/use_suggestion_json.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index 2ebe212b93d..fd3b5fe1ada 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -1,2 +1,290 @@
-{"message":"cannot find type `Iter` in this scope","code":{"code":"E0412","explanation":"/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n    fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n    type N;/n/n    fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n    fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n    // either/n    use super::File;/n    // or/n    // use std::fs::File;/n    fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"},"level":"error","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":862,"byte_end":866,"line_start":20,"line_end":20,"column_start":12,"column_end":16,"is_primary":true,"text":[{"text":"    let x: Iter;","highlight_start":12,"highlight_end":16}],"label":"not found in this scope","suggested_replacement":null,"expansion":null}],"children":[{"message":"possible candidates are found in other modules, you can import them into scope","code":null,"level":"help","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::binary_heap::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::linked_list::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::vec_deque::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::option::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::path::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::result::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::slice::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::sync::mpsc::Iter;/n/n","expansion":null}],"children":[],"rendered":null}],"rendered":null}
-{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":null}
+{
+  "message": "cannot find type `Iter` in this scope",
+  "code": {
+    "code": "E0412",
+    "explanation": "/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n    fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n    type N;/n/n    fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n    fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n    // either/n    use super::File;/n    // or/n    // use std::fs::File;/n    fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"
+  },
+  "level": "error",
+  "spans": [
+    {
+      "file_name": "$DIR/use_suggestion_json.rs",
+      "byte_start": 888,
+      "byte_end": 892,
+      "line_start": 20,
+      "line_end": 20,
+      "column_start": 12,
+      "column_end": 16,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let x: Iter;",
+          "highlight_start": 12,
+          "highlight_end": 16
+        }
+      ],
+      "label": "not found in this scope",
+      "suggested_replacement": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "possible candidates are found in other modules, you can import them into scope",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::binary_heap::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_map::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_set::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_map::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_set::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::linked_list::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::vec_deque::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::option::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::path::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::result::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::slice::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::sync::mpsc::Iter;/n/n",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": null
+}
+{
+  "message": "aborting due to previous error",
+  "code": null,
+  "level": "error",
+  "spans": [],
+  "children": [],
+  "rendered": null
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 9d4ac630546..9de5e8fea01 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -14,15 +14,6 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
    |               |
    |               expected closure that takes 2 arguments
 
-error[E0308]: mismatched types
-  --> $DIR/closure-arg-count.rs:17:24
-   |
-17 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
-   |                        ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
-   |
-   = note: expected type `&{integer}`
-              found type `(_, _)`
-
 error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:17:15
    |
@@ -65,5 +56,5 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t
    |                                                     |
    |                                                     expected closure that takes a single 2-tuple as argument
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/nll/named-region-basic.rs b/src/test/ui/nll/named-region-basic.rs
new file mode 100644
index 00000000000..539c2017ea6
--- /dev/null
+++ b/src/test/ui/nll/named-region-basic.rs
@@ -0,0 +1,22 @@
+// 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
+
+fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
+    &*x
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/named-region-basic.stderr b/src/test/ui/nll/named-region-basic.stderr
new file mode 100644
index 00000000000..42b2aea01f0
--- /dev/null
+++ b/src/test/ui/nll/named-region-basic.stderr
@@ -0,0 +1,29 @@
+warning: not reporting region error due to -Znll
+  --> $DIR/named-region-basic.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error[E0597]: `*x` does not live long enough
+  --> $DIR/named-region-basic.rs:19:6
+   |
+19 |     &*x
+   |      ^^ 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
+20 | | }
+   | |_^
+
+error: free region `'a` does not outlive `'b`
+  --> $DIR/named-region-basic.rs:19:5
+   |
+19 |     &*x
+   |     ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
index 281c21f6f85..6bd63f4fbbb 100644
--- a/src/test/ui/resolve/token-error-correct.stderr
+++ b/src/test/ui/resolve/token-error-correct.stderr
@@ -28,29 +28,11 @@ error: expected expression, found `;`
 14 |     foo(bar(;
    |             ^
 
-error: expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `for`, `if`, `loop`, `match`, `move`, `return`, `true`, `unsafe`, `while`, `yield`, or an operator, found `;`
-  --> $DIR/token-error-correct.rs:14:13
-   |
-14 |     foo(bar(;
-   |             ^ expected one of 19 possible tokens here
-
 error: expected expression, found `)`
   --> $DIR/token-error-correct.rs:23:1
    |
 23 | }
    | ^
 
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/token-error-correct.rs:14:5
-   |
-14 |     foo(bar(;
-   |     ^^^ not found in this scope
-
-error[E0425]: cannot find function `bar` in this scope
-  --> $DIR/token-error-correct.rs:14:9
-   |
-14 |     foo(bar(;
-   |         ^^^ not found in this scope
-
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs b/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs
new file mode 100644
index 00000000000..52ff817dff4
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    if let Some(y) = &Some(22) {
+      println!("{}", y);
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
new file mode 100644
index 00000000000..0594f865f32
--- /dev/null
+++ b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
@@ -0,0 +1,10 @@
+error: non-reference pattern used to match a reference (see issue #42640)
+  --> $DIR/suggestion.rs:12:12
+   |
+12 |     if let Some(y) = &Some(22) {
+   |            ^^^^^^^ help: consider using: `&Some(y)`
+   |
+   = help: add #![feature(match_default_bindings)] to the crate attributes to enable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/E0535.rs b/src/test/ui/span/E0535.rs
index 17558cc05c6..f9219436c78 100644
--- a/src/test/ui/span/E0535.rs
+++ b/src/test/ui/span/E0535.rs
@@ -11,4 +11,6 @@
 #[inline(unknown)] //~ ERROR E0535
 pub fn something() {}
 
-fn main() {}
+fn main() {
+    something();
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs b/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs
new file mode 100644
index 00000000000..bcd965f10fa
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs
@@ -0,0 +1,13 @@
+// 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.
+
+fn main() {
+    let x: Vec::with_capacity(10, 20);
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr b/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr
new file mode 100644
index 00000000000..647e3f84685
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr
@@ -0,0 +1,17 @@
+error: expected type, found `10`
+  --> $DIR/type-ascription-instead-of-initializer.rs:12:31
+   |
+12 |     let x: Vec::with_capacity(10, 20);
+   |         --                    ^^
+   |         ||
+   |         |help: use `=` if you meant to assign
+   |         while parsing the type for `x`
+
+error[E0061]: this function takes 1 parameter but 2 parameters were supplied
+  --> $DIR/type-ascription-instead-of-initializer.rs:12:31
+   |
+12 |     let x: Vec::with_capacity(10, 20);
+   |                               ^^^^^^ expected 1 parameter
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 859c2305b5d7ff820d7f7af158bbca999cbd8bf
+Subproject b83550edc300e3d80dd16d0440123ffc1ad77bb
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 4f4960efc9b..a6c56a13076 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -165,6 +165,8 @@ fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bo
     let status = command
         // Disable rust-lang/cargo's cross-compile tests
         .env("CFG_DISABLE_CROSS_TESTS", "1")
+        // Relax #![deny(warnings)] in some crates
+        .env("RUSTFLAGS", "--cap-lints warn")
         .current_dir(crate_path)
         .status()
         .expect("");
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index aa98f818f40..660462ad419 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -34,6 +34,20 @@ pub enum Mode {
     MirOpt,
 }
 
+impl Mode {
+    pub fn disambiguator(self) -> &'static str {
+        // Run-pass and pretty run-pass tests could run concurrently, and if they do,
+        // they need to keep their output segregated. Same is true for debuginfo tests that
+        // can be run both on gdb and lldb.
+        match self {
+            Pretty => ".pretty",
+            DebugInfoGdb => ".gdb",
+            DebugInfoLldb => ".lldb",
+            _ => "",
+        }
+    }
+}
+
 impl FromStr for Mode {
     type Err = ();
     fn from_str(s: &str) -> Result<Mode, ()> {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 0473c2a5405..f02525c118a 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1384,6 +1384,7 @@ actual:\n\
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
             rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
+            rustc.args(&["-Z", "incremental-verify-ich"]);
         }
 
         match self.config.mode {
@@ -1404,6 +1405,7 @@ actual:\n\
                     "-Zdump-mir-exclude-pass-number"]);
 
                 let mir_dump_dir = self.get_mir_dump_dir();
+                let _ = fs::remove_dir_all(&mir_dump_dir);
                 create_dir_all(mir_dump_dir.as_path()).unwrap();
                 let mut dir_opt = "-Zdump-mir-dir=".to_string();
                 dir_opt.push_str(mir_dump_dir.to_str().unwrap());
@@ -1564,7 +1566,7 @@ actual:\n\
     fn aux_output_dir_name(&self) -> PathBuf {
         let f = self.output_base_name();
         let mut fname = f.file_name().unwrap().to_os_string();
-        fname.push(&format!(".{}.libaux", self.config.mode));
+        fname.push(&format!("{}.aux", self.config.mode.disambiguator()));
         f.with_file_name(&fname)
     }
 
@@ -2285,6 +2287,10 @@ actual:\n\
         output_file.push(test_name);
         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());
+        }
         self.check_mir_test_timestamp(test_name, &output_file);
 
         let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
@@ -2333,13 +2339,22 @@ actual:\n\
 
         // We expect each non-empty line to appear consecutively, non-consecutive lines
         // must be separated by at least one Elision
+        let mut start_block_line = None;
         while let Some(dumped_line) = dumped_lines.next() {
             match expected_lines.next() {
-                Some(&ExpectedLine::Text(expected_line)) =>
+                Some(&ExpectedLine::Text(expected_line)) => {
+                    let normalized_expected_line = normalize_mir_line(expected_line);
+                    if normalized_expected_line.contains(":{") {
+                        start_block_line = Some(expected_line);
+                    }
+
                     if !compare(expected_line, dumped_line) {
+                        error!("{:?}", start_block_line);
                         error(expected_line,
-                              format!("Mismatch in lines\nExpected Line: {:?}", dumped_line));
-                    },
+                              format!("Mismatch in lines\nCurrnt block: {}\nExpected 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() {
@@ -2367,19 +2382,18 @@ actual:\n\
     }
 
     fn get_mir_dump_dir(&self) -> PathBuf {
-        let mut mir_dump_dir = PathBuf::from(self.config.build_base
-                                                    .as_path()
-                                                    .to_str()
-                                                    .unwrap());
+        let mut mir_dump_dir = PathBuf::from(self.config.build_base.as_path());
         debug!("input_file: {:?}", self.testpaths.file);
-        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap().to_str().unwrap());
+        mir_dump_dir.push(&self.testpaths.relative_dir);
+        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap());
         mir_dump_dir
     }
 
     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 parent_dir_str = if cflags.contains("--error-format json") {
+        let parent_dir_str = if cflags.contains("--error-format json")
+                             || cflags.contains("--error-format pretty-json") {
             parent_dir.display().to_string().replace("\\", "\\\\")
         } else {
             parent_dir.display().to_string()
diff --git a/src/tools/rls b/src/tools/rls
-Subproject e0348594a724571f1d2387e03943efeb4df20e1
+Subproject 9ad92e134ff56df52481cf19dc3da14b9e73506
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
-Subproject cf0d494dda7447bacaab743a70c47e28bea55c6
+Subproject 51b03c3aaf5e69afbb7508e566c5da2bf0bc366