about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNikolai Vazquez <nvazquez1297@gmail.com>2017-09-30 10:08:33 -0400
committerNikolai Vazquez <nvazquez1297@gmail.com>2017-09-30 10:08:33 -0400
commit4c853adce9103b8bc84cd6b0026bcdc2eed7da31 (patch)
treef71af0eb9d7139af598684355e690596721eac1b /src
parentd9d877221f65b26e52f49bfc639ef705ff396deb (diff)
parentc4cca3a72df87def5cb18ff500c643fbff8ad08e (diff)
downloadrust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.tar.gz
rust-4c853adce9103b8bc84cd6b0026bcdc2eed7da31.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock449
-rw-r--r--src/Cargo.toml7
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bin/sccache-plus-cl.rs4
-rw-r--r--src/bootstrap/bootstrap.py2
-rw-r--r--src/bootstrap/builder.rs7
-rw-r--r--src/bootstrap/cc_detect.rs (renamed from src/bootstrap/cc.rs)10
-rw-r--r--src/bootstrap/check.rs12
-rw-r--r--src/bootstrap/clean.rs35
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/dist.rs17
-rw-r--r--src/bootstrap/flags.rs21
-rw-r--r--src/bootstrap/lib.rs16
-rw-r--r--src/bootstrap/native.rs9
-rw-r--r--src/bootstrap/sanity.rs5
-rw-r--r--src/bootstrap/tool.rs13
-rw-r--r--src/bootstrap/toolstate.rs2
-rw-r--r--src/ci/docker/cross/Dockerfile5
-rwxr-xr-xsrc/ci/docker/cross/build-arm-musl.sh27
-rw-r--r--src/ci/docker/disabled/aarch64-gnu/Dockerfile2
-rw-r--r--src/ci/docker/disabled/wasm32-exp/Dockerfile2
-rw-r--r--src/ci/docker/dist-fuchsia/Dockerfile29
-rwxr-xr-xsrc/ci/docker/dist-fuchsia/build-toolchain.sh109
-rw-r--r--src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch41
-rwxr-xr-xsrc/ci/docker/run.sh8
-rw-r--r--src/doc/unstable-book/src/language-features/inclusive-range-syntax.md4
-rw-r--r--src/liballoc/arc.rs13
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/tests/btree/map.rs28
-rw-r--r--src/liballoc/tests/str.rs16
-rw-r--r--src/liballoc/tests/string.rs6
-rw-r--r--src/liballoc/tests/vec.rs28
-rw-r--r--src/liballoc/vec.rs12
-rw-r--r--src/liballoc/vec_deque.rs18
-rw-r--r--src/liballoc_jemalloc/Cargo.toml2
-rw-r--r--src/liballoc_jemalloc/build.rs6
-rw-r--r--src/libcore/benches/iter.rs151
-rw-r--r--src/libcore/cmp.rs4
-rw-r--r--src/libcore/convert.rs41
-rw-r--r--src/libcore/fmt/mod.rs24
-rw-r--r--src/libcore/internal_macros.rs19
-rw-r--r--src/libcore/iter/iterator.rs4
-rw-r--r--src/libcore/iter/mod.rs233
-rw-r--r--src/libcore/iter/range.rs2
-rw-r--r--src/libcore/iter/traits.rs64
-rw-r--r--src/libcore/marker.rs2
-rw-r--r--src/libcore/mem.rs50
-rw-r--r--src/libcore/num/mod.rs50
-rw-r--r--src/libcore/num/wrapping.rs12
-rw-r--r--src/libcore/ops/arith.rs10
-rw-r--r--src/libcore/ops/bit.rs10
-rw-r--r--src/libcore/ops/range.rs50
-rw-r--r--src/libcore/ops/unsize.rs2
-rw-r--r--src/libcore/option.rs28
-rw-r--r--src/libcore/ptr.rs2
-rw-r--r--src/libcore/slice/mod.rs15
-rw-r--r--src/libcore/str/mod.rs24
-rw-r--r--src/libcore/sync/atomic.rs28
-rw-r--r--src/libcore/tests/char.rs1
-rw-r--r--src/libcore/tests/iter.rs212
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/libcore/tests/num/mod.rs10
-rw-r--r--src/libcore/tests/option.rs27
-rw-r--r--src/libcore/tests/result.rs29
m---------src/liblibc0
-rw-r--r--src/libproc_macro/lib.rs2
-rw-r--r--src/libproc_macro/quote.rs4
-rw-r--r--src/libprofiler_builtins/Cargo.toml2
-rw-r--r--src/libprofiler_builtins/build.rs4
-rw-r--r--src/librustc/README.md2
-rw-r--r--src/librustc/dep_graph/dep_node.rs88
-rw-r--r--src/librustc/dep_graph/edges.rs7
-rw-r--r--src/librustc/dep_graph/graph.rs351
-rw-r--r--src/librustc/dep_graph/mod.rs14
-rw-r--r--src/librustc/dep_graph/prev.rs46
-rw-r--r--src/librustc/dep_graph/raii.rs41
-rw-r--r--src/librustc/dep_graph/serialized.rs63
-rw-r--r--src/librustc/diagnostics.rs109
-rw-r--r--src/librustc/hir/def_id.rs11
-rw-r--r--src/librustc/hir/intravisit.rs11
-rw-r--r--src/librustc/hir/lowering.rs97
-rw-r--r--src/librustc/hir/map/collector.rs191
-rw-r--r--src/librustc/hir/map/mod.rs49
-rw-r--r--src/librustc/hir/mod.rs86
-rw-r--r--src/librustc/hir/print.rs47
-rw-r--r--src/librustc/ich/caching_codemap_view.rs1
-rw-r--r--src/librustc/ich/hcx.rs18
-rw-r--r--src/librustc/ich/impls_hir.rs42
-rw-r--r--src/librustc/ich/impls_mir.rs38
-rw-r--r--src/librustc/ich/impls_syntax.rs2
-rw-r--r--src/librustc/ich/impls_ty.rs12
-rw-r--r--src/librustc/infer/error_reporting/different_lifetimes.rs122
-rw-r--r--src/librustc/infer/error_reporting/mod.rs99
-rw-r--r--src/librustc/infer/error_reporting/named_anon_conflict.rs52
-rw-r--r--src/librustc/infer/error_reporting/util.rs11
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/builtin.rs2
-rw-r--r--src/librustc/lint/levels.rs5
-rw-r--r--src/librustc/middle/cstore.rs6
-rw-r--r--src/librustc/middle/dead.rs28
-rw-r--r--src/librustc/middle/dependency_format.rs86
-rw-r--r--src/librustc/middle/effect.rs316
-rw-r--r--src/librustc/middle/free_region.rs2
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/middle/reachable.rs3
-rw-r--r--src/librustc/middle/region.rs142
-rw-r--r--src/librustc/middle/resolve_lifetime.rs82
-rw-r--r--src/librustc/mir/mod.rs72
-rw-r--r--src/librustc/mir/visit.rs2
-rw-r--r--src/librustc/session/config.rs127
-rw-r--r--src/librustc/session/mod.rs3
-rw-r--r--src/librustc/traits/error_reporting.rs141
-rw-r--r--src/librustc/traits/trans/mod.rs11
-rw-r--r--src/librustc/ty/context.rs49
-rw-r--r--src/librustc/ty/maps/mod.rs7
-rw-r--r--src/librustc/ty/maps/plumbing.rs2
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/util/common.rs5
-rw-r--r--src/librustc/util/ppaux.rs21
-rw-r--r--src/librustc_back/target/aarch64_unknown_linux_musl.rs36
-rw-r--r--src/librustc_back/target/mod.rs1
-rw-r--r--src/librustc_data_structures/bitvec.rs2
-rw-r--r--src/librustc_data_structures/stable_hasher.rs34
-rw-r--r--src/librustc_data_structures/transitive_relation.rs6
-rw-r--r--src/librustc_driver/driver.rs183
-rw-r--r--src/librustc_driver/lib.rs84
-rw-r--r--src/librustc_driver/pretty.rs11
-rw-r--r--src/librustc_driver/profile/trace.rs4
-rw-r--r--src/librustc_driver/test.rs5
-rw-r--r--src/librustc_incremental/calculate_svh/mod.rs331
-rw-r--r--src/librustc_incremental/lib.rs5
-rw-r--r--src/librustc_incremental/persist/data.rs8
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs105
-rw-r--r--src/librustc_incremental/persist/fs.rs125
-rw-r--r--src/librustc_incremental/persist/hash.rs227
-rw-r--r--src/librustc_incremental/persist/load.rs87
-rw-r--r--src/librustc_incremental/persist/mod.rs2
-rw-r--r--src/librustc_incremental/persist/preds/mod.rs14
-rw-r--r--src/librustc_incremental/persist/save.rs63
-rw-r--r--src/librustc_lint/bad_style.rs2
-rw-r--r--src/librustc_lint/unused.rs18
-rw-r--r--src/librustc_llvm/Cargo.toml2
-rw-r--r--src/librustc_llvm/build.rs4
-rw-r--r--src/librustc_metadata/cstore_impl.rs21
-rw-r--r--src/librustc_mir/borrow_check.rs750
-rw-r--r--src/librustc_mir/build/block.rs83
-rw-r--r--src/librustc_mir/build/expr/as_constant.rs2
-rw-r--r--src/librustc_mir/build/expr/as_lvalue.rs4
-rw-r--r--src/librustc_mir/build/expr/as_operand.rs4
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs5
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs4
-rw-r--r--src/librustc_mir/build/expr/into.rs24
-rw-r--r--src/librustc_mir/build/expr/stmt.rs4
-rw-r--r--src/librustc_mir/build/matches/mod.rs23
-rw-r--r--src/librustc_mir/build/mod.rs55
-rw-r--r--src/librustc_mir/build/scope.rs51
-rw-r--r--src/librustc_mir/diagnostics.rs34
-rw-r--r--src/librustc_mir/hair/cx/block.rs15
-rw-r--r--src/librustc_mir/hair/cx/expr.rs26
-rw-r--r--src/librustc_mir/hair/cx/mod.rs48
-rw-r--r--src/librustc_mir/hair/mod.rs31
-rw-r--r--src/librustc_mir/shim.rs5
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs387
-rw-r--r--src/librustc_mir/transform/generator.rs24
-rw-r--r--src/librustc_mir/transform/mod.rs3
-rw-r--r--src/librustc_mir/transform/nll/mod.rs (renamed from src/librustc_mir/transform/nll.rs)0
-rw-r--r--src/librustc_mir/transform/promote_consts.rs8
-rw-r--r--src/librustc_passes/ast_validation.rs8
-rw-r--r--src/librustc_privacy/Cargo.toml1
-rw-r--r--src/librustc_privacy/lib.rs155
-rw-r--r--src/librustc_resolve/lib.rs54
-rw-r--r--src/librustc_trans/Cargo.toml2
-rw-r--r--src/librustc_trans/back/link.rs58
-rw-r--r--src/librustc_trans/back/write.rs11
-rw-r--r--src/librustc_trans/base.rs85
-rw-r--r--src/librustc_trans/lib.rs60
-rw-r--r--src/librustc_trans/monomorphize.rs6
-rw-r--r--src/librustc_trans/partitioning.rs5
-rw-r--r--src/librustc_trans_utils/Cargo.toml8
-rw-r--r--src/librustc_trans_utils/lib.rs81
-rw-r--r--src/librustc_trans_utils/link.rs47
-rw-r--r--src/librustc_trans_utils/trans_crate.rs249
-rw-r--r--src/librustc_typeck/astconv.rs136
-rw-r--r--src/librustc_typeck/check/_match.rs13
-rw-r--r--src/librustc_typeck/check/coercion.rs6
-rw-r--r--src/librustc_typeck/check/demand.rs33
-rw-r--r--src/librustc_typeck/check/method/confirm.rs7
-rw-r--r--src/librustc_typeck/check/method/mod.rs3
-rw-r--r--src/librustc_typeck/check/method/probe.rs86
-rw-r--r--src/librustc_typeck/check/method/suggest.rs5
-rw-r--r--src/librustc_typeck/check/mod.rs48
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs7
-rw-r--r--src/librustc_typeck/collect.rs17
-rw-r--r--src/librustc_typeck/diagnostics.rs2
-rw-r--r--src/librustc_typeck/impl_wf_check.rs2
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/build.rs4
-rw-r--r--src/librustdoc/clean/mod.rs42
-rw-r--r--src/librustdoc/core.rs4
-rw-r--r--src/librustdoc/html/highlight.rs6
-rw-r--r--src/librustdoc/html/render.rs6
-rw-r--r--src/librustdoc/html/static/rustdoc.css2
-rw-r--r--src/librustdoc/test.rs18
-rw-r--r--src/libstd/Cargo.toml2
-rw-r--r--src/libstd/build.rs8
-rw-r--r--src/libstd/collections/hash/map.rs41
-rw-r--r--src/libstd/error.rs8
-rw-r--r--src/libstd/fs.rs27
-rw-r--r--src/libstd/io/util.rs3
-rw-r--r--src/libstd/net/tcp.rs2
-rw-r--r--src/libstd/primitive_docs.rs8
-rw-r--r--src/libstd/process.rs32
-rw-r--r--src/libstd/sync/rwlock.rs133
-rw-r--r--src/libstd/sys/unix/ext/fs.rs4
-rw-r--r--src/libstd/sys/unix/fs.rs2
-rw-r--r--src/libstd/sys/unix/process/mod.rs2
-rw-r--r--src/libstd/sys/unix/process/process_fuchsia.rs76
-rw-r--r--src/libstd/sys/unix/process/zircon.rs (renamed from src/libstd/sys/unix/process/magenta.rs)182
-rw-r--r--src/libstd/sys/unix/rand.rs8
-rw-r--r--src/libstd/sys_common/poison.rs57
-rw-r--r--src/libstd/time/duration.rs23
-rw-r--r--src/libsyntax/ast.rs10
-rw-r--r--src/libsyntax/diagnostic_list.rs4
-rw-r--r--src/libsyntax/ext/base.rs4
-rw-r--r--src/libsyntax/ext/expand.rs73
-rw-r--r--src/libsyntax/ext/quote.rs2
-rw-r--r--src/libsyntax/feature_gate.rs30
-rw-r--r--src/libsyntax/parse/lexer/mod.rs3
-rw-r--r--src/libsyntax/parse/parser.rs71
-rw-r--r--src/libsyntax/parse/token.rs35
-rw-r--r--src/libsyntax/print/pprust.rs7
-rw-r--r--src/libsyntax/util/parser.rs17
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs11
-rw-r--r--src/libsyntax_pos/hygiene.rs2
-rw-r--r--src/libsyntax_pos/lib.rs64
-rw-r--r--src/libsyntax_pos/span_encoding.rs143
-rw-r--r--src/rtstartup/rsbegin.rs2
-rw-r--r--src/rtstartup/rsend.rs2
-rw-r--r--src/rustc/libc_shim/Cargo.toml32
-rw-r--r--src/test/compile-fail/E0506.rs7
-rw-r--r--src/test/compile-fail/E0586.rs2
-rw-r--r--src/test/compile-fail/E0637.rs20
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-comp.rs15
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs36
-rw-r--r--src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs7
-rw-r--r--src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs7
-rw-r--r--src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs23
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs4
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs7
-rw-r--r--src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs7
-rw-r--r--src/test/compile-fail/borrowck/borrowck-union-borrow.rs50
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs7
-rw-r--r--src/test/compile-fail/cdylib-deps-must-be-static.rs2
-rw-r--r--src/test/compile-fail/coerce-overloaded-autoderef.rs19
-rw-r--r--src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs16
-rw-r--r--src/test/compile-fail/feature-gate-underscore-lifetimes.rs (renamed from src/rustc/libc_shim/build.rs)12
-rw-r--r--src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs24
-rw-r--r--src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs5
-rw-r--r--src/test/compile-fail/hrtb-identity-fn-borrows.rs7
-rw-r--r--src/test/compile-fail/impossible_range.rs8
-rw-r--r--src/test/compile-fail/issue-43023.rs28
-rw-r--r--src/test/compile-fail/issue-43733.rs4
-rw-r--r--src/test/compile-fail/label-underscore.rs (renamed from src/test/compile-fail/lifetime-underscore.rs)6
-rw-r--r--src/test/compile-fail/lint-stability-deprecated.rs1
-rw-r--r--src/test/compile-fail/mut-pattern-internal-mutability.rs11
-rw-r--r--src/test/compile-fail/object-lifetime-default-mybox.rs2
-rw-r--r--src/test/compile-fail/private-inferred-type.rs5
-rw-r--r--src/test/compile-fail/private-type-in-interface.rs1
-rw-r--r--src/test/compile-fail/range_inclusive_gate.rs2
-rw-r--r--src/test/compile-fail/regions-pattern-typing-issue-19997.rs7
-rw-r--r--src/test/compile-fail/rmeta_lib.rs2
-rw-r--r--src/test/compile-fail/synthetic-param.rs38
-rw-r--r--src/test/compile-fail/type-path-err-node-types.rs17
-rw-r--r--src/test/compile-fail/underscore-lifetime-binders.rs39
-rw-r--r--src/test/compile-fail/underscore-lifetime-elison-mismatch.rs15
-rw-r--r--src/test/compile-fail/union/union-unsafe.rs4
-rw-r--r--src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs3
-rw-r--r--src/test/compile-fail/unsafe-move-val-init.rs20
-rw-r--r--src/test/incremental/callee_caller_cross_crate/b.rs2
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs2
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs2
-rw-r--r--src/test/incremental/dirty_clean.rs4
-rw-r--r--src/test/incremental/hashes/enum_defs.rs2
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs2
-rw-r--r--src/test/incremental/rlib_cross_crate/b.rs2
-rw-r--r--src/test/incremental/string_constant.rs5
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/b.rs2
-rw-r--r--src/test/incremental/type_alias_cross_crate/b.rs2
-rw-r--r--src/test/parse-fail/pat-ranges-1.rs2
-rw-r--r--src/test/parse-fail/pat-ranges-2.rs2
-rw-r--r--src/test/parse-fail/pat-ranges-3.rs2
-rw-r--r--src/test/parse-fail/pat-ranges-4.rs3
-rw-r--r--src/test/parse-fail/range_inclusive.rs2
-rw-r--r--src/test/parse-fail/range_inclusive_gate.rs14
-rw-r--r--src/test/run-make/codegen-options-parsing/Makefile30
-rw-r--r--src/test/run-make/llvm-phase/test.rs1
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs (renamed from src/test/ui/mismatched_types/E0281.rs)38
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs32
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs23
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs27
-rw-r--r--src/test/run-pass-valgrind/issue-44800.rs25
-rw-r--r--src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs4
-rw-r--r--src/test/run-pass/ifmt.rs12
-rw-r--r--src/test/run-pass/inc-range-pat.rs22
-rw-r--r--src/test/run-pass/issue-44730.rs24
-rw-r--r--src/test/run-pass/num-wrapping.rs9
-rw-r--r--src/test/run-pass/op-assign-builtins-by-ref.rs84
-rw-r--r--src/test/run-pass/range_inclusive.rs68
-rw-r--r--src/test/run-pass/range_inclusive_gate.rs2
-rw-r--r--src/test/run-pass/underscore-lifetimes.rs47
-rw-r--r--src/test/rustdoc/pub-method.rs31
-rw-r--r--src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr2
-rw-r--r--src/test/ui/block-result/issue-3563.stderr2
-rw-r--r--src/test/ui/deref-suggestion.rs34
-rw-r--r--src/test/ui/deref-suggestion.stderr59
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr28
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr28
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr28
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr23
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr23
-rw-r--r--src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs (renamed from src/test/compile-fail/issue-16747.rs)8
-rw-r--r--src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr30
-rw-r--r--src/test/ui/mismatched_types/E0281.stderr13
-rw-r--r--src/test/ui/mismatched_types/E0631.rs21
-rw-r--r--src/test/ui/mismatched_types/E0631.stderr44
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.rs4
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr28
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.rs21
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr45
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr7
-rw-r--r--src/test/ui/mismatched_types/fn-variance-1.stderr14
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr7
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr9
-rw-r--r--src/test/ui/path-lookahead.stderr12
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr6
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.rs9
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.stderr29
-rw-r--r--src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs10
-rw-r--r--src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr34
-rw-r--r--src/test/ui/span/issue-35987.stderr2
-rw-r--r--src/test/ui/span/issue-43927-non-ADT-derive.rs16
-rw-r--r--src/test/ui/span/issue-43927-non-ADT-derive.stderr8
-rw-r--r--src/test/ui/span/unused-warning-point-at-signature.rs40
-rw-r--r--src/test/ui/span/unused-warning-point-at-signature.stderr36
-rw-r--r--src/test/ui/suggestions/suggest-methods.rs40
-rw-r--r--src/test/ui/suggestions/suggest-methods.stderr32
-rw-r--r--src/test/ui/suggestions/try-on-option.rs25
-rw-r--r--src/test/ui/suggestions/try-on-option.stderr22
-rw-r--r--src/test/ui/type-check/issue-41314.rs19
-rw-r--r--src/test/ui/type-check/issue-41314.stderr16
-rw-r--r--src/tools/build-manifest/src/main.rs22
m---------src/tools/cargo0
-rw-r--r--src/tools/cargotest/main.rs2
m---------src/tools/rls0
m---------src/tools/rustfmt14
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--src/tools/toolstate.toml9
360 files changed, 7945 insertions, 4158 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 3a9d9ad9c54..c77be5154d3 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1,10 +1,6 @@
 [root]
-name = "unwind"
-version = "0.0.0"
-dependencies = [
- "core 0.0.0",
- "libc 0.0.0",
-]
+name = "workspace_symbol"
+version = "0.1.0"
 
 [[package]]
 name = "advapi32-sys"
@@ -46,8 +42,8 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -80,31 +76,31 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "backtrace"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "backtrace-sys"
-version = "0.1.12"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -140,16 +136,16 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -166,8 +162,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -175,7 +171,7 @@ dependencies = [
 name = "build_helper"
 version = "0.1.0"
 dependencies = [
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -193,8 +189,8 @@ dependencies = [
  "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -205,20 +201,20 @@ dependencies = [
  "ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -233,13 +229,13 @@ name = "cargotest"
 version = "0.1.0"
 dependencies = [
  "cargo 0.23.0",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -249,13 +245,18 @@ name = "cargotest2"
 version = "0.1.0"
 
 [[package]]
+name = "cc"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "cfg-if"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "clap"
-version = "2.26.0"
+version = "2.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -263,8 +264,7 @@ dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -272,10 +272,10 @@ dependencies = [
 
 [[package]]
 name = "cmake"
-version = "0.1.25"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -300,9 +300,9 @@ version = "0.0.0"
 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)",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -332,7 +332,7 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -340,7 +340,7 @@ name = "core-foundation-sys"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -349,9 +349,9 @@ version = "0.12.0"
 dependencies = [
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -394,23 +394,23 @@ name = "curl"
 version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -459,8 +459,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -500,7 +500,7 @@ name = "error-chain"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -508,7 +508,7 @@ name = "error-chain"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -520,10 +520,11 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.1.10"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -540,11 +541,11 @@ version = "0.1.0"
 
 [[package]]
 name = "flate2"
-version = "0.2.19"
+version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -567,7 +568,7 @@ version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -582,7 +583,7 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -592,7 +593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "getopts"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -601,10 +602,10 @@ version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -661,10 +662,10 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -753,9 +754,9 @@ version = "0.1.0"
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -766,7 +767,7 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -774,20 +775,20 @@ name = "jobserver"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "jsonrpc-core"
-version = "7.1.0"
+version = "7.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -816,9 +817,9 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -837,21 +838,21 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.30"
+version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.6.14"
+version = "0.6.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -860,20 +861,20 @@ name = "libssh2-sys"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libz-sys"
-version = "1.0.16"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -889,12 +890,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lzma-sys"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -942,18 +944,18 @@ name = "mdbook"
 version = "0.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -963,7 +965,7 @@ name = "memchr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -971,16 +973,16 @@ name = "memchr"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "miniz-sys"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1005,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1081,7 +1083,7 @@ name = "num_cpus"
 version = "1.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1090,19 +1092,19 @@ version = "0.1.0"
 
 [[package]]
 name = "open"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl"
-version = "0.9.17"
+version = "0.9.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1112,11 +1114,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.17"
+version = "0.9.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1219,8 +1221,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1238,12 +1240,12 @@ version = "0.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "quick-error"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1261,7 +1263,7 @@ name = "racer"
 version = "2.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1282,11 +1284,16 @@ name = "rand"
 version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.1.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "reformat"
 version = "0.1.0"
 
@@ -1346,26 +1353,26 @@ version = "0.122.0"
 dependencies = [
  "cargo 0.23.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (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.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.10.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.5",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.2.7",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rls-analysis"
-version = "0.6.7"
+version = "0.6.8"
 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)",
@@ -1382,8 +1389,8 @@ 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)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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)",
 ]
 
 [[package]]
@@ -1397,8 +1404,8 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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)",
 ]
 
 [[package]]
@@ -1414,7 +1421,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1424,7 +1431,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1482,7 +1489,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1621,7 +1628,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
 
@@ -1632,7 +1639,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1640,7 +1647,7 @@ dependencies = [
 name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
@@ -1677,7 +1684,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1715,6 +1722,7 @@ name = "rustc_privacy"
 version = "0.0.0"
 dependencies = [
  "rustc 0.0.0",
+ "rustc_typeck 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -1751,8 +1759,8 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1777,7 +1785,12 @@ dependencies = [
 name = "rustc_trans_utils"
 version = "0.0.0"
 dependencies = [
+ "ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_back 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -1789,7 +1802,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1815,8 +1828,8 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1831,18 +1844,18 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.5"
+version = "0.2.7"
 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)",
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1890,7 +1903,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1900,22 +1913,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.11"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.11"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_derive_internals"
-version = "0.15.1"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1927,18 +1940,18 @@ name = "serde_ignored"
 version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1962,12 +1975,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "socket2"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1985,10 +1998,10 @@ dependencies = [
  "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
+ "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -2018,7 +2031,7 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2116,7 +2129,7 @@ name = "syntex_errors"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2138,7 +2151,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2152,8 +2165,8 @@ name = "tar"
 version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2194,7 +2207,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2210,13 +2223,13 @@ dependencies = [
 name = "test"
 version = "0.0.0"
 dependencies = [
- "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.0.0",
 ]
 
 [[package]]
 name = "textwrap"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2229,7 +2242,7 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2266,7 +2279,7 @@ name = "toml"
 version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2308,6 +2321,10 @@ version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "unicødë"
+version = "0.1.0"
+
+[[package]]
 name = "unreachable"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2331,6 +2348,14 @@ dependencies = [
 ]
 
 [[package]]
+name = "unwind"
+version = "0.0.0"
+dependencies = [
+ "core 0.0.0",
+ "libc 0.0.0",
+]
+
+[[package]]
 name = "url"
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2345,7 +2370,7 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2434,7 +2459,7 @@ name = "xattr"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2442,7 +2467,7 @@ name = "xz2"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2457,16 +2482,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
 "checksum ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b24e4eef8e3fa7e2ca75b157e6039cdf8d9d3a68213ddc19d0fd9d576b9717c9"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
-"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
-"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c"
+"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983"
+"checksum backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c63ea141ef8fdb10409d0f5daf30ac51f84ef43bff66f16627773d2a292cd189"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
+"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
-"checksum cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8a6541a55bcd72d3de4faee2d101a5a66df29790282c7f797082a7228a9b3d"
+"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2"
+"checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d"
 "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
 "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
 "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
@@ -2475,7 +2501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef6124306e5ebc5ab11891d063aeafdd0cdc308079b708c8b566125f3680292b"
 "checksum cssparser-macros 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "079adec4af52bb5275eadd004292028c79eb3c5f5b4ee8086a36d4197032f6df"
 "checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c"
-"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de"
+"checksum curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4bee31aa3a079d5f3ff9579ea4dcfb1b1a17a40886f5f467436d383e78134b55"
 "checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
 "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"
@@ -2488,15 +2514,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
 "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
-"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
+"checksum filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab199bf38537c6f38792669e081e0bb278b9b7405bba2642e4e5d15bf732c0e"
+"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
 "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344"
 "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
-"checksum futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a82bdc62350ca9d7974c760e9665102fc9d740992a528c2254aa930e53b783c4"
+"checksum futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "05a23db7bd162d4e8265968602930c476f688f0c180b44bdaf55e0cb2c687558"
 "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
-"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
+"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9"
 "checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa"
 "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
@@ -2509,19 +2535,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum html5ever 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a49d5001dd1bddf042ea41ed4e0a671d50b1bf187e66b349d7ec613bdce4ad90"
 "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
 "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
-"checksum itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac17257442c2ed77dbc9fd555cf83c58b0c7f7d0e8f2ae08c0ac05c72842e1f6"
+"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
 "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133"
-"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf"
+"checksum jsonrpc-core 7.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1acd0f9934da94466d2370f36832b9b19271b4abdfdb5e69f0bcd991ebcd515"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum kuchiki 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ef2ea4f2f7883cd7c6772b06c14abca01a2cc1f75c426cebffcf6b3b925ef9fc"
 "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf"
 "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
-"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915"
-"checksum libgit2-sys 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c00f6e5bc3fb2b5f87e75e8d0fd4ae6720d55f3ee23d389b7c6cae30f8db8db1"
+"checksum libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d1419b2939a0bc44b77feb34661583c7546b532b192feab36249ab584b86856c"
+"checksum libgit2-sys 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "205fc37e829c5b36de63d14c8dc8b62c5a6a2519b16318ed0977079ca97256a9"
 "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
-"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
+"checksum libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "44ebbc760fd2d2f4d93de09a0e13d97e057612052e871da9985cedcb451e6bd5"
 "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
-"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b"
+"checksum lzma-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c1b93b78f89e8737dac81837fc8f5521ac162abcba902e1a3db949d55346d1da"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527"
 "checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699"
@@ -2530,7 +2556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "146eadfc6d141452a364c351f07bb19208d1401e931f40b8532f87bba3ecc40f"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
-"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
+"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
 "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
@@ -2541,10 +2567,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
 "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
 "checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
-"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
-"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5"
+"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
+"checksum openssl 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "816914b22eb15671d62c73442a51978f311e911d6a6f6cbdafa6abce1b5038fc"
 "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3"
+"checksum openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4c63a7d559c1e5afa6d6a9e6fa34bbc5f800ffc9ae08b72c605420b0c4f5e8"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
@@ -2557,16 +2583,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum procedural-masquerade 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c93cdc1fb30af9ddf3debc4afbdb0f35126cbd99daa229dd76cdd5349b41d989"
 "checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478"
 "checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
-"checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
+"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "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.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf"
+"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "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.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4302cc8291570d7f817945845d8c01756e833dbc93c0a87d4f6c9a0b0b7992f1"
+"checksum rls-analysis 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa390bdc70b0a90d07d9cd5c6989ba5fca2d59728903919ebda1a1b2037b18d7"
 "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
 "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"
@@ -2579,15 +2606,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum selectors 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c89b1c6a3c029c82263f7dd2d44d0005ee7374eb09e254ab59dede4353a8c0"
 "checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
-"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"
-"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
+"checksum serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7046c9d4c6c522d10b2d098f9bebe2bef227e0e74044d8c1bfcf6b476af799"
+"checksum serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1afcaae083fd1c46952a315062326bc9957f182358eb7da03b57ef1c688f7aa9"
+"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58"
 "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142"
-"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
+"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
 "checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e"
-"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a"
+"checksum socket2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e76b159741052c7deaa9fd0b5ca6b5f79cecf525ed665abfe5002086c6b2791"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string_cache 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "413fc7852aeeb5472f1986ef755f561ddf0c789d3d796e65f0b6fe293ecd4ef8"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
@@ -2606,7 +2633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9065bced9c3e43453aa3d56f1e98590b8455b341d2fa191a1090c0dd0b242c75"
-"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6"
+"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
diff --git a/src/Cargo.toml b/src/Cargo.toml
index 12c074b6a41..f4b4189e01f 100644
--- a/src/Cargo.toml
+++ b/src/Cargo.toml
@@ -38,6 +38,8 @@ members = [
   "tools/rls/test_data/infer_custom_bin",
   "tools/rls/test_data/infer_lib",
   "tools/rls/test_data/omit_init_build",
+  "tools/rls/test_data/unicødë",
+  "tools/rls/test_data/workspace_symbol",
 ]
 
 # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
@@ -60,10 +62,5 @@ debug-assertions = false
 [patch."https://github.com/rust-lang/cargo"]
 cargo = { path = "tools/cargo" }
 
-# Override rustfmt dependencies both on the repo and the crate (the RLS
-# sometimes uses either).
-# FIXME should only need the crates.io patch, long term.
-[patch."https://github.com/rust-lang-nursery/rustfmt"]
-rustfmt-nightly = { path = "tools/rustfmt" }
 [patch.crates-io]
 rustfmt-nightly = { path = "tools/rustfmt" }
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 85e3b65c195..3f1d03b1872 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -34,7 +34,7 @@ cmake = "0.1.23"
 filetime = "0.1"
 num_cpus = "1.0"
 getopts = "0.2"
-gcc = "0.3.54"
+cc = "1.0"
 libc = "0.2"
 serde = "1.0.8"
 serde_derive = "1.0.8"
diff --git a/src/bootstrap/bin/sccache-plus-cl.rs b/src/bootstrap/bin/sccache-plus-cl.rs
index 266dffa5c92..8584014d48d 100644
--- a/src/bootstrap/bin/sccache-plus-cl.rs
+++ b/src/bootstrap/bin/sccache-plus-cl.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate gcc;
+extern crate cc;
 
 use std::env;
 use std::process::{self, Command};
@@ -18,7 +18,7 @@ fn main() {
     // Locate the actual compiler that we're invoking
     env::remove_var("CC");
     env::remove_var("CXX");
-    let mut cfg = gcc::Build::new();
+    let mut cfg = cc::Build::new();
     cfg.cargo_metadata(false)
        .out_dir("/")
        .target(&target)
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f12da29c45b..4a8c3dcebcb 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -682,7 +682,7 @@ def bootstrap():
     try:
         with open(args.config or 'config.toml') as config:
             build.config_toml = config.read()
-    except OSError:
+    except (OSError, IOError):
         pass
 
     if '\nverbose = 2' in build.config_toml:
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 8a6c998c932..e7a5196178c 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -306,7 +306,7 @@ impl<'a> Builder<'a> {
             Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
             Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
             Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
-            Subcommand::Clean => panic!(),
+            Subcommand::Clean { .. } => panic!(),
         };
 
         let builder = Builder {
@@ -531,7 +531,10 @@ impl<'a> Builder<'a> {
         // For other crates, however, we know that we've already got a standard
         // library up and running, so we can use the normal compiler to compile
         // build scripts in that situation.
-        if mode == Mode::Libstd {
+        //
+        // If LLVM support is disabled we need to use the snapshot compiler to compile
+        // build scripts, as the new compiler doesnt support executables.
+        if mode == Mode::Libstd || !self.build.config.llvm_enabled {
             cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
         } else {
diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc_detect.rs
index c77e609d70b..08df65c7611 100644
--- a/src/bootstrap/cc.rs
+++ b/src/bootstrap/cc_detect.rs
@@ -23,7 +23,7 @@
 //! 6. "cc"
 //!
 //! Some of this logic is implemented here, but much of it is farmed out to the
-//! `gcc` crate itself, so we end up having the same fallbacks as there.
+//! `cc` crate itself, so we end up having the same fallbacks as there.
 //! Similar logic is then used to find a C++ compiler, just some s/cc/c++/ is
 //! used.
 //!
@@ -35,7 +35,7 @@ use std::process::Command;
 use std::iter;
 
 use build_helper::{cc2ar, output};
-use gcc;
+use cc;
 
 use Build;
 use config::Target;
@@ -45,7 +45,7 @@ pub fn find(build: &mut Build) {
     // For all targets we're going to need a C compiler for building some shims
     // and such as well as for being a linker for Rust code.
     for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) {
-        let mut cfg = gcc::Build::new();
+        let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
            .target(&target).host(&build.build);
 
@@ -67,7 +67,7 @@ pub fn find(build: &mut Build) {
 
     // For all host triples we need to find a C++ compiler as well
     for host in build.hosts.iter().cloned().chain(iter::once(build.build)) {
-        let mut cfg = gcc::Build::new();
+        let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
            .target(&host).host(&build.build);
         let config = build.config.target_config.get(&host);
@@ -82,7 +82,7 @@ pub fn find(build: &mut Build) {
     }
 }
 
-fn set_compiler(cfg: &mut gcc::Build,
+fn set_compiler(cfg: &mut cc::Build,
                 gnu_compiler: &str,
                 target: Interned<String>,
                 config: Option<&Target>,
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 21e7a052362..6e276f44668 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -254,7 +254,11 @@ impl Step for Rls {
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        try_run(build, &mut cargo);
+        try_run_expecting(
+            build,
+            &mut cargo,
+            builder.build.config.toolstate.rls.passes(ToolState::Testing),
+        );
     }
 }
 
@@ -295,7 +299,11 @@ impl Step for Rustfmt {
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        try_run(build, &mut cargo);
+        try_run_expecting(
+            build,
+            &mut cargo,
+            builder.build.config.toolstate.rustfmt.passes(ToolState::Testing),
+        );
     }
 }
 
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 119340a0190..87f194fb7d2 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -13,7 +13,7 @@
 //! Responsible for cleaning out a build directory of all old and stale
 //! artifacts to prepare for a fresh build. Currently doesn't remove the
 //! `build/cache` directory (download cache) or the `build/$target/llvm`
-//! directory as we want that cached between builds.
+//! directory unless the --all flag is present.
 
 use std::fs;
 use std::io::{self, ErrorKind};
@@ -21,24 +21,29 @@ use std::path::Path;
 
 use Build;
 
-pub fn clean(build: &Build) {
+pub fn clean(build: &Build, all: bool) {
     rm_rf("tmp".as_ref());
-    rm_rf(&build.out.join("tmp"));
-    rm_rf(&build.out.join("dist"));
 
-    for host in &build.hosts {
-        let entries = match build.out.join(host).read_dir() {
-            Ok(iter) => iter,
-            Err(_) => continue,
-        };
+    if all {
+        rm_rf(&build.out);
+    } else {
+        rm_rf(&build.out.join("tmp"));
+        rm_rf(&build.out.join("dist"));
 
-        for entry in entries {
-            let entry = t!(entry);
-            if entry.file_name().to_str() == Some("llvm") {
-                continue
+        for host in &build.hosts {
+            let entries = match build.out.join(host).read_dir() {
+                Ok(iter) => iter,
+                Err(_) => continue,
+            };
+
+            for entry in entries {
+                let entry = t!(entry);
+                if entry.file_name().to_str() == Some("llvm") {
+                    continue
+                }
+                let path = t!(entry.path().canonicalize());
+                rm_rf(&path);
             }
-            let path = t!(entry.path().canonicalize());
-            rm_rf(&path);
         }
     }
 }
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 2438be89776..67337bf4421 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -109,6 +109,8 @@ v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root",
   "arm-unknown-linux-musleabihf install directory")
 v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root",
   "armv7-unknown-linux-musleabihf install directory")
+v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root",
+  "aarch64-unknown-linux-musl install directory")
 v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
   "rootfs in qemu testing, you probably don't want to use this")
 v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs",
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 5188604b0a6..3d4aa0413db 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1098,13 +1098,8 @@ impl Step for Rls {
            .arg("--output-dir").arg(&distdir(build))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, target))
-           .arg("--legacy-manifest-dirs=rustlib,cargo");
-
-        if build.config.channel == "nightly" {
-            cmd.arg("--component-name=rls");
-        } else {
-            cmd.arg("--component-name=rls-preview");
-        }
+           .arg("--legacy-manifest-dirs=rustlib,cargo")
+           .arg("--component-name=rls-preview");
 
         build.run(&mut cmd);
         distdir(build).join(format!("{}-{}.tar.gz", name, target))
@@ -1333,12 +1328,8 @@ impl Step for Extended {
             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target))
                         .join(format!("rust-std-{}", target)),
                     &exe.join("rust-std"));
-            let rls_path = if build.config.channel == "nightly" {
-                work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls")
-            } else {
-                work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview")
-            };
-            cp_r(&rls_path, &exe.join("rls"));
+            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview"),
+                 &exe.join("rls"));
             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target))
                         .join(format!("rust-analysis-{}", target)),
                     &exe.join("rust-analysis"));
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 7546d7fd4f0..df378188b4a 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -60,7 +60,9 @@ pub enum Subcommand {
         paths: Vec<PathBuf>,
         test_args: Vec<String>,
     },
-    Clean,
+    Clean {
+        all: bool,
+    },
     Dist {
         paths: Vec<PathBuf>,
     },
@@ -147,6 +149,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
                 opts.optmulti("", "test-args", "extra arguments", "ARGS");
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
+            "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
             _ => { },
         };
 
@@ -250,7 +253,7 @@ Arguments:
             }
         });
 
-        // All subcommands can have an optional "Available paths" section
+        // All subcommands except `clean` can have an optional "Available paths" section
         if matches.opt_present("verbose") {
             let config = Config::parse(&["build".to_string()]);
             let mut build = Build::new(config);
@@ -258,9 +261,10 @@ Arguments:
 
             let maybe_rules_help = Builder::get_help(&build, subcommand.as_str());
             extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str());
-        } else {
-            extra_help.push_str(format!("Run `./x.py {} -h -v` to see a list of available paths.",
-                     subcommand).as_str());
+        } else if subcommand.as_str() != "clean" {
+            extra_help.push_str(format!(
+                "Run `./x.py {} -h -v` to see a list of available paths.",
+                subcommand).as_str());
         }
 
         // User passed in -h/--help?
@@ -290,10 +294,13 @@ Arguments:
             }
             "clean" => {
                 if paths.len() > 0 {
-                    println!("\nclean takes no arguments\n");
+                    println!("\nclean does not take a path argument\n");
                     usage(1, &opts, &subcommand_help, &extra_help);
                 }
-                Subcommand::Clean
+
+                Subcommand::Clean {
+                    all: matches.opt_present("all"),
+                }
             }
             "dist" => {
                 Subcommand::Dist {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 06c7c4c2faf..2d721f45578 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -126,7 +126,7 @@ extern crate lazy_static;
 extern crate serde_json;
 extern crate cmake;
 extern crate filetime;
-extern crate gcc;
+extern crate cc;
 extern crate getopts;
 extern crate num_cpus;
 extern crate toml;
@@ -148,7 +148,7 @@ use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppresse
 
 use util::{exe, libdir, OutputFolder, CiEnv};
 
-mod cc;
+mod cc_detect;
 mod channel;
 mod check;
 mod clean;
@@ -241,9 +241,9 @@ pub struct Build {
 
     // Runtime state filled in later on
     // target -> (cc, ar)
-    cc: HashMap<Interned<String>, (gcc::Tool, Option<PathBuf>)>,
+    cc: HashMap<Interned<String>, (cc::Tool, Option<PathBuf>)>,
     // host -> (cc, ar)
-    cxx: HashMap<Interned<String>, gcc::Tool>,
+    cxx: HashMap<Interned<String>, cc::Tool>,
     crates: HashMap<Interned<String>, Crate>,
     is_sudo: bool,
     ci_env: CiEnv,
@@ -345,12 +345,12 @@ impl Build {
             job::setup(self);
         }
 
-        if let Subcommand::Clean = self.config.cmd {
-            return clean::clean(self);
+        if let Subcommand::Clean { all } = self.config.cmd {
+            return clean::clean(self, all);
         }
 
         self.verbose("finding compilers");
-        cc::find(self);
+        cc_detect::find(self);
         self.verbose("running sanity check");
         sanity::check(self);
         // If local-rust is the same major.minor as the current version, then force a local-rebuild
@@ -619,7 +619,7 @@ impl Build {
     /// specified.
     fn cflags(&self, target: Interned<String>) -> Vec<String> {
         // Filter out -O and /O (the optimization flags) that we picked up from
-        // gcc-rs because the build scripts will determine that for themselves.
+        // cc-rs because the build scripts will determine that for themselves.
         let mut base = self.cc[&target].0.args().iter()
                            .map(|s| s.to_string_lossy().into_owned())
                            .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 99077d03dbe..c4e80630315 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -27,7 +27,7 @@ use std::process::Command;
 
 use build_helper::output;
 use cmake;
-use gcc;
+use cc;
 
 use Build;
 use util;
@@ -289,7 +289,7 @@ impl Step for TestHelpers {
         let _folder = build.fold_output(|| "build_test_helpers");
         println!("Building test helpers");
         t!(fs::create_dir_all(&dst));
-        let mut cfg = gcc::Build::new();
+        let mut cfg = cc::Build::new();
 
         // We may have found various cross-compilers a little differently due to our
         // extra configuration, so inform gcc of these compilers. Note, though, that
@@ -367,7 +367,7 @@ impl Step for Openssl {
             if !ok {
                 panic!("failed to download openssl source")
             }
-            let mut shasum = if target.contains("apple") {
+            let mut shasum = if target.contains("apple") || build.build.contains("netbsd") {
                 let mut cmd = Command::new("shasum");
                 cmd.arg("-a").arg("256");
                 cmd
@@ -387,7 +387,7 @@ impl Step for Openssl {
         let dst = build.openssl_install_dir(target).unwrap();
         drop(fs::remove_dir_all(&obj));
         drop(fs::remove_dir_all(&dst));
-        build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out));
+        build.run(Command::new("tar").arg("zxf").arg(&tarball).current_dir(&out));
 
         let mut configure = Command::new("perl");
         configure.arg(obj.join("Configure"));
@@ -399,6 +399,7 @@ impl Step for Openssl {
         let os = match &*target {
             "aarch64-linux-android" => "linux-aarch64",
             "aarch64-unknown-linux-gnu" => "linux-aarch64",
+            "aarch64-unknown-linux-musl" => "linux-aarch64",
             "arm-linux-androideabi" => "android",
             "arm-unknown-linux-gnueabi" => "linux-armv4",
             "arm-unknown-linux-gnueabihf" => "linux-armv4",
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 54208d8bb57..8b23be69a85 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -221,8 +221,9 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
     let run = |cmd: &mut Command| {
         cmd.output().map(|output| {
             String::from_utf8_lossy(&output.stdout)
-                   .lines().next().unwrap()
-                   .to_string()
+                   .lines().next().unwrap_or_else(|| {
+                       panic!("{:?} failed {:?}", cmd, output)
+                   }).to_string()
         })
     };
     build.lldb_version = run(Command::new("lldb").arg("--version")).ok();
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index db794f6d6c7..a05e58e6a22 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -126,6 +126,10 @@ pub fn prepare_tool_cargo(
         cargo.env("LIBZ_SYS_STATIC", "1");
     }
 
+    // if tools are using lzma we want to force the build script to build its
+    // own copy
+    cargo.env("LZMA_API_STATIC", "1");
+
     cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);
     cargo.env("CFG_VERSION", build.rust_version());
 
@@ -304,6 +308,11 @@ impl Step for Rustdoc {
                                            target,
                                            "build",
                                            "src/tools/rustdoc");
+
+        // Most tools don't get debuginfo, but rustdoc should.
+        cargo.env("RUSTC_DEBUGINFO", builder.config.rust_debuginfo.to_string())
+             .env("RUSTC_DEBUGINFO_LINES", builder.config.rust_debuginfo_lines.to_string());
+
         build.run(&mut cargo);
         // Cargo adds a number of paths to the dylib search path on windows, which results in
         // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
@@ -449,7 +458,7 @@ impl Step for Rls {
             tool: "rls",
             mode: Mode::Librustc,
             path: "src/tools/rls",
-            expectation: BuildExpectation::None,
+            expectation: builder.build.config.toolstate.rls.passes(ToolState::Compiling),
         })
     }
 }
@@ -484,7 +493,7 @@ impl Step for Rustfmt {
             tool: "rustfmt",
             mode: Mode::Librustc,
             path: "src/tools/rustfmt",
-            expectation: BuildExpectation::None,
+            expectation: builder.build.config.toolstate.rustfmt.passes(ToolState::Compiling),
         })
     }
 }
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 0711c034602..8a113f6b4d2 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -46,4 +46,6 @@ impl Default for ToolState {
 pub struct ToolStates {
     pub miri: ToolState,
     pub clippy: ToolState,
+    pub rls: ToolState,
+    pub rustfmt: ToolState,
 }
diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile
index a83bbe9c60e..05745709a07 100644
--- a/src/ci/docker/cross/Dockerfile
+++ b/src/ci/docker/cross/Dockerfile
@@ -14,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   g++-arm-linux-gnueabi \
   g++-arm-linux-gnueabihf \
+  g++-aarch64-linux-gnu \
   gcc-sparc64-linux-gnu \
   libc6-dev-sparc64-cross \
   bzip2 \
@@ -46,6 +47,7 @@ ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
+ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
 ENV TARGETS=$TARGETS,x86_64-unknown-redox
 
@@ -62,7 +64,8 @@ ENV RUST_CONFIGURE_ARGS \
       --target=$TARGETS \
       --musl-root-arm=/usr/local/arm-linux-musleabi \
       --musl-root-armhf=/usr/local/arm-linux-musleabihf \
-      --musl-root-armv7=/usr/local/armv7-linux-musleabihf
+      --musl-root-armv7=/usr/local/armv7-linux-musleabihf \
+      --musl-root-aarch64=/usr/local/aarch64-linux-musl
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
 
 # sccache
diff --git a/src/ci/docker/cross/build-arm-musl.sh b/src/ci/docker/cross/build-arm-musl.sh
index 938e69834e4..780099e2ec1 100755
--- a/src/ci/docker/cross/build-arm-musl.sh
+++ b/src/ci/docker/cross/build-arm-musl.sh
@@ -65,11 +65,24 @@ CFLAGS="-march=armv7-a" \
 hide_output make -j$(nproc)
 hide_output make install
 cd ..
+rm -rf musl-$MUSL
+
+tar xf musl-$MUSL.tar.gz
+cd musl-$MUSL
+CC=aarch64-linux-gnu-gcc \
+CFLAGS="" \
+    hide_output ./configure \
+        --prefix=/usr/local/aarch64-linux-musl \
+        --enable-wrapper=gcc
+hide_output make -j$(nproc)
+hide_output make install
+cd ..
 rm -rf musl-$MUSL*
 
 ln -nsf ../arm-linux-musleabi/bin/musl-gcc /usr/local/bin/arm-linux-musleabi-gcc
 ln -nsf ../arm-linux-musleabihf/bin/musl-gcc /usr/local/bin/arm-linux-musleabihf-gcc
 ln -nsf ../armv7-linux-musleabihf/bin/musl-gcc /usr/local/bin/armv7-linux-musleabihf-gcc
+ln -nsf ../aarch64-linux-musl/bin/musl-gcc /usr/local/bin/aarch64-unknown-linux-musl-gcc
 
 curl -L https://github.com/llvm-mirror/llvm/archive/release_39.tar.gz | tar xzf -
 curl -L https://github.com/llvm-mirror/libunwind/archive/release_39.tar.gz | tar xzf -
@@ -116,5 +129,19 @@ cp lib/libunwind.a /usr/local/armv7-linux-musleabihf/lib
 cd ..
 rm -rf libunwind-build
 
+mkdir libunwind-build
+cd libunwind-build
+cmake ../libunwind-release_39 \
+          -DLLVM_PATH=/tmp/llvm-release_39 \
+          -DLIBUNWIND_ENABLE_SHARED=0 \
+          -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
+          -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
+          -DCMAKE_C_FLAGS="" \
+          -DCMAKE_CXX_FLAGS=""
+make -j$(nproc)
+cp lib/libunwind.a /usr/local/aarch64-linux-musl/lib
+cd ..
+rm -rf libunwind-build
+
 rm -rf libunwind-release_39
 rm -rf llvm-release_39
diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
index 9a0e4531223..fedb4094c8a 100644
--- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
@@ -31,7 +31,7 @@ WORKDIR /build
 # The `config` config file was a previously generated config file for
 # the kernel. This file was generated by running `make defconfig`
 # followed by `make menuconfig` and then enabling the IPv6 protocol page.
-COPY disabled/aarch64-gnu/config /build/.config
+COPY aarch64-gnu/config /build/.config
 RUN curl https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.42.tar.xz | \
       tar xJf - && \
       cd /build/linux-4.4.42 && \
diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile
index 6323369421b..8653b0e8b46 100644
--- a/src/ci/docker/disabled/wasm32-exp/Dockerfile
+++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 
 # emscripten
 COPY scripts/emscripten-wasm.sh /scripts/
-COPY disabled/wasm32-exp/node.sh /usr/local/bin/node
+COPY wasm32-exp/node.sh /usr/local/bin/node
 RUN bash /scripts/emscripten-wasm.sh
 
 # cache
diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile
index e18cb453baf..bcd95924b42 100644
--- a/src/ci/docker/dist-fuchsia/Dockerfile
+++ b/src/ci/docker/dist-fuchsia/Dockerfile
@@ -1,27 +1,26 @@
 FROM ubuntu:16.04
 
-RUN apt-get update && apt-get install -y --no-install-recommends \
+RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y \
+  build-essential \
+  bzip2 \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
   g++ \
+  gdb \
+  git \
+  libedit-dev \
   make \
   ninja-build \
-  file \
-  curl \
-  ca-certificates \
+  nodejs \
   python2.7-dev \
-  git \
   sudo \
-  bzip2 \
   xz-utils \
-  swig \
-  libedit-dev \
-  libncurses5-dev \
-  patch
-
-RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \
-      tar xzf - -C /usr/local --strip-components=1
+  unzip
 
 WORKDIR /tmp
-COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/
+COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh /tmp/
 RUN /tmp/build-toolchain.sh
 
 COPY scripts/sccache.sh /scripts/
@@ -39,4 +38,4 @@ ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
-ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
+ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
\ No newline at end of file
diff --git a/src/ci/docker/dist-fuchsia/build-toolchain.sh b/src/ci/docker/dist-fuchsia/build-toolchain.sh
index 10b285a5466..756013a235c 100755
--- a/src/ci/docker/dist-fuchsia/build-toolchain.sh
+++ b/src/ci/docker/dist-fuchsia/build-toolchain.sh
@@ -14,105 +14,44 @@
 set -ex
 source shared.sh
 
-# Download sources
-SRCS=(
-  "https://fuchsia.googlesource.com/magenta magenta d17073dc8de344ead3b65e8cc6a12280dec38c84"
-  "https://llvm.googlesource.com/llvm llvm 3f58a16d8eec385e2b3ebdfbb84ff9d3bf27e025"
-  "https://llvm.googlesource.com/clang llvm/tools/clang 727ea63e6e82677f6e10e05e08bc7d6bdbae3111"
-  "https://llvm.googlesource.com/lld llvm/tools/lld a31286c1366e5e89b8872803fded13805a1a084b"
-  "https://llvm.googlesource.com/lldb llvm/tools/lldb 0b2384abec4cb99ad66687712e07dee4dd9d187e"
-  "https://llvm.googlesource.com/compiler-rt llvm/runtimes/compiler-rt 9093a35c599fe41278606a20b51095ea8bd5a081"
-  "https://llvm.googlesource.com/libcxx llvm/runtimes/libcxx 607e0c71ec4f7fd377ad3f6c47b08dbe89f66eaa"
-  "https://llvm.googlesource.com/libcxxabi llvm/runtimes/libcxxabi 0a3a1a8a5ca5ef69e0f6b7d5b9d13e63e6fd2c19"
-  "https://llvm.googlesource.com/libunwind llvm/runtimes/libunwind e128003563d99d9ee62247c4cee40f07d21c03e3"
-)
-
-fetch() {
-  mkdir -p $2
-  pushd $2 > /dev/null
-  git init
-  git remote add origin $1
-  git fetch --depth=1 origin $3
-  git reset --hard FETCH_HEAD
-  popd > /dev/null
-}
+ZIRCON=e9a26dbc70d631029f8ee9763103910b7e3a2fe1
 
-for i in "${SRCS[@]}"; do
-  fetch $i
-done
+mkdir -p zircon
+pushd zircon > /dev/null
 
-# Remove this once https://reviews.llvm.org/D28791 is resolved
-cd llvm/runtimes/compiler-rt
-patch -Np1 < /tmp/compiler-rt-dso-handle.patch
-cd ../../..
+# Download sources
+git init
+git remote add origin https://fuchsia.googlesource.com/zircon
+git fetch --depth=1 origin $ZIRCON
+git reset --hard FETCH_HEAD
 
-# Build toolchain
-cd llvm
-mkdir build
-cd build
-hide_output cmake -GNinja \
-  -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \
-  -DLLVM_ENABLE_LTO=OFF \
-  -DCLANG_BOOTSTRAP_PASSTHROUGH=LLVM_ENABLE_LTO \
-  -C ../tools/clang/cmake/caches/Fuchsia.cmake \
-  ..
-hide_output ninja stage2-distribution
-hide_output ninja stage2-install-distribution
-cd ../..
+# Download toolchain
+./scripts/download-toolchain
+chmod -R a+rx prebuilt/downloads/clang+llvm-x86_64-linux
+cp -a prebuilt/downloads/clang+llvm-x86_64-linux/. /usr/local
 
-# Build sysroot
-rm -rf llvm/runtimes/compiler-rt
-./magenta/scripts/download-toolchain
-
-build_sysroot() {
+build() {
   local arch="$1"
 
   case "${arch}" in
-    x86_64) tgt="magenta-pc-x86-64" ;;
-    aarch64) tgt="magenta-qemu-arm64" ;;
+    x86_64) tgt="zircon-pc-x86-64" ;;
+    aarch64) tgt="zircon-qemu-arm64" ;;
   esac
 
-  hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt
+  hide_output make -j$(getconf _NPROCESSORS_ONLN) $tgt
   dst=/usr/local/${arch}-unknown-fuchsia
   mkdir -p $dst
-  cp -r magenta/build-${tgt}/sysroot/include $dst/
-  cp -r magenta/build-${tgt}/sysroot/lib $dst/
-
-  cd llvm
-  mkdir build-runtimes-${arch}
-  cd build-runtimes-${arch}
-  hide_output cmake -GNinja \
-    -DCMAKE_C_COMPILER=clang \
-    -DCMAKE_CXX_COMPILER=clang++ \
-    -DCMAKE_AR=/usr/local/bin/llvm-ar \
-    -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \
-    -DCMAKE_INSTALL_PREFIX= \
-    -DLLVM_MAIN_SRC_DIR=${PWD}/.. \
-    -DLLVM_BINARY_DIR=${PWD}/../build \
-    -DLLVM_ENABLE_WERROR=OFF \
-    -DCMAKE_BUILD_TYPE=Release \
-    -DLLVM_INCLUDE_TESTS=ON \
-    -DCMAKE_SYSTEM_NAME=Fuchsia \
-    -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \
-    -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \
-    -DUNIX=1 \
-    -DLIBCXX_HAS_MUSL_LIBC=ON \
-    -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
-    -DCMAKE_SYSROOT=${dst} \
-    -DCMAKE_C_COMPILER_FORCED=TRUE \
-    -DCMAKE_CXX_COMPILER_FORCED=TRUE \
-    -DLLVM_ENABLE_LIBCXX=ON \
-    -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \
-    -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \
-    ../runtimes
-  hide_output env DESTDIR="${dst}" ninja install
-  cd ../..
+  cp -a build-${tgt}/sysroot/include $dst/
+  cp -a build-${tgt}/sysroot/lib $dst/
 }
 
-build_sysroot "x86_64"
-build_sysroot "aarch64"
+# Build sysroot
+for arch in x86_64 aarch64; do
+  build ${arch}
+done
 
-rm -rf magenta llvm
+popd > /dev/null
+rm -rf zircon
 
 for arch in x86_64 aarch64; do
   for tool in clang clang++; do
diff --git a/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch b/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch
deleted file mode 100644
index 0b702894bb2..00000000000
--- a/src/ci/docker/dist-fuchsia/compiler-rt-dso-handle.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-diff --git a/lib/builtins/CMakeLists.txt b/lib/builtins/CMakeLists.txt
-index fc4384af2..b442264c0 100644
---- a/lib/builtins/CMakeLists.txt
-+++ b/lib/builtins/CMakeLists.txt
-@@ -194,6 +194,12 @@ if(APPLE)
-     atomic_thread_fence.c)
- endif()
- 
-+if(FUCHSIA)
-+  set(GENERIC_SOURCES
-+    ${GENERIC_SOURCES}
-+    dso_handle.c)
-+endif()
-+
- if(NOT WIN32 OR MINGW)
-   set(GENERIC_SOURCES
-       ${GENERIC_SOURCES}
-diff --git a/lib/builtins/dso_handle.c b/lib/builtins/dso_handle.c
-new file mode 100644
-index 000000000..7766cd0aa
---- /dev/null
-+++ b/lib/builtins/dso_handle.c
-@@ -0,0 +1,18 @@
-+/* ===-- dso_handle.c - Provide __dso_handle -------------------------------===
-+ *
-+ *               The LLVM Compiler Infrastructure
-+ *
-+ * This file is dual licensed under the MIT and the University of Illinois Open
-+ * Source Licenses. See LICENSE.TXT for details.
-+ *
-+ * ===----------------------------------------------------------------------===
-+ */
-+
-+/* __dso_handle symbol is mandated by C++ ABI with a value which is an address
-+ * in one of the object's segments, and as such this symbol has to be included
-+ * statically and cannot be a part of a shared library. Traditionally, it has
-+ * been defined in crtbegin.o but there's no principled reason for it to be
-+ * there. We defined this symbol in the builtin library which is built as a
-+ * static library and always included in the final link.
-+ */
-+__attribute__((visibility("hidden"))) void *const __dso_handle;
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 7087033e117..b2560c6b95b 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -36,12 +36,14 @@ elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
         echo Cannot run disabled images on travis!
         exit 1
     fi
-    retry docker \
+    # retry messes with the pipe from tar to docker. Not needed on non-travis
+    # Transform changes the context of disabled Dockerfiles to match the enabled ones
+    tar --transform 's#^./disabled/#./#' -C $docker_dir -c . | docker \
       build \
       --rm \
       -t rust-ci \
-      -f "$docker_dir/disabled/$image/Dockerfile" \
-      "$docker_dir"
+      -f "$image/Dockerfile" \
+      -
 else
     echo Invalid image: $image
     exit 1
diff --git a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md
index 255445c318d..56f58803150 100644
--- a/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md
+++ b/src/doc/unstable-book/src/language-features/inclusive-range-syntax.md
@@ -7,13 +7,13 @@ The tracking issue for this feature is: [#28237]
 ------------------------
 
 To get a range that goes from 0 to 10 and includes the value 10, you
-can write `0...10`:
+can write `0..=10`:
 
 ```rust
 #![feature(inclusive_range_syntax)]
 
 fn main() {
-    for i in 0...10 {
+    for i in 0..=10 {
         println!("{}", i);
     }
 }
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 4b695ad7c79..3b7dbd813cf 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -72,13 +72,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// first: after all, isn't the point of `Arc<T>` thread safety? The key is
 /// this: `Arc<T>` makes it thread safe to have multiple ownership of the same
 /// data, but it  doesn't add thread safety to its data. Consider
-/// `Arc<RefCell<T>>`. `RefCell<T>` isn't [`Sync`], and if `Arc<T>` was always
-/// [`Send`], `Arc<RefCell<T>>` would be as well. But then we'd have a problem:
-/// `RefCell<T>` is not thread safe; it keeps track of the borrowing count using
+/// `Arc<`[`RefCell<T>`]`>`. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always
+/// [`Send`], `Arc<`[`RefCell<T>`]`>` would be as well. But then we'd have a problem:
+/// [`RefCell<T>`] is not thread safe; it keeps track of the borrowing count using
 /// non-atomic operations.
 ///
 /// In the end, this means that you may need to pair `Arc<T>` with some sort of
-/// `std::sync` type, usually `Mutex<T>`.
+/// [`std::sync`] type, usually [`Mutex<T>`][mutex].
 ///
 /// ## Breaking cycles with `Weak`
 ///
@@ -106,7 +106,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// // a and b both point to the same memory location as foo.
 /// ```
 ///
-/// The `Arc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly
+/// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly
 /// the meaning of the code. In the example above, this syntax makes it easier to see that
 /// this code is creating a new reference rather than copying the whole content of foo.
 ///
@@ -141,6 +141,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// [upgrade]: struct.Weak.html#method.upgrade
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 /// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
+/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
+/// [`std::sync`]: ../../std/sync/index.html
+/// [`Arc::clone(&from)`]: #method.clone
 ///
 /// # Examples
 ///
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 2845d349ae1..d51aaa23c6a 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -98,6 +98,7 @@
 #![feature(generic_param_attrs)]
 #![feature(i128_type)]
 #![feature(inclusive_range)]
+#![feature(iter_rfold)]
 #![feature(lang_items)]
 #![feature(needs_allocator)]
 #![feature(nonzero)]
diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs
index 2c899d96940..2393101040d 100644
--- a/src/liballoc/tests/btree/map.rs
+++ b/src/liballoc/tests/btree/map.rs
@@ -182,7 +182,7 @@ fn test_range_small() {
 fn test_range_inclusive() {
     let size = 500;
 
-    let map: BTreeMap<_, _> = (0...size).map(|i| (i, i)).collect();
+    let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect();
 
     fn check<'a, L, R>(lhs: L, rhs: R)
         where L: IntoIterator<Item=(&'a i32, &'a i32)>,
@@ -193,18 +193,18 @@ fn test_range_inclusive() {
         assert_eq!(lhs, rhs);
     }
 
-    check(map.range(size + 1...size + 1), vec![]);
-    check(map.range(size...size), vec![(&size, &size)]);
-    check(map.range(size...size + 1), vec![(&size, &size)]);
-    check(map.range(0...0), vec![(&0, &0)]);
-    check(map.range(0...size - 1), map.range(..size));
-    check(map.range(-1...-1), vec![]);
-    check(map.range(-1...size), map.range(..));
-    check(map.range(...size), map.range(..));
-    check(map.range(...200), map.range(..201));
-    check(map.range(5...8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
-    check(map.range(-1...0), vec![(&0, &0)]);
-    check(map.range(-1...2), vec![(&0, &0), (&1, &1), (&2, &2)]);
+    check(map.range(size + 1..=size + 1), vec![]);
+    check(map.range(size..=size), vec![(&size, &size)]);
+    check(map.range(size..=size + 1), vec![(&size, &size)]);
+    check(map.range(0..=0), vec![(&0, &0)]);
+    check(map.range(0..=size - 1), map.range(..size));
+    check(map.range(-1..=-1), vec![]);
+    check(map.range(-1..=size), map.range(..));
+    check(map.range(..=size), map.range(..));
+    check(map.range(..=200), map.range(..201));
+    check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
+    check(map.range(-1..=0), vec![(&0, &0)]);
+    check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
 }
 
 #[test]
@@ -212,7 +212,7 @@ fn test_range_inclusive_max_value() {
     let max = ::std::usize::MAX;
     let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
 
-    assert_eq!(map.range(max...max).collect::<Vec<_>>(), &[(&max, &0)]);
+    assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
 }
 
 #[test]
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index 9d8ca38b20e..b3178064505 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -361,13 +361,13 @@ fn test_slice_fail() {
 #[test]
 #[should_panic]
 fn test_str_slice_rangetoinclusive_max_panics() {
-    &"hello"[...usize::max_value()];
+    &"hello"[..=usize::max_value()];
 }
 
 #[test]
 #[should_panic]
 fn test_str_slice_rangeinclusive_max_panics() {
-    &"hello"[1...usize::max_value()];
+    &"hello"[1..=usize::max_value()];
 }
 
 #[test]
@@ -375,7 +375,7 @@ fn test_str_slice_rangeinclusive_max_panics() {
 fn test_str_slicemut_rangetoinclusive_max_panics() {
     let mut s = "hello".to_owned();
     let s: &mut str = &mut s;
-    &mut s[...usize::max_value()];
+    &mut s[..=usize::max_value()];
 }
 
 #[test]
@@ -383,7 +383,7 @@ fn test_str_slicemut_rangetoinclusive_max_panics() {
 fn test_str_slicemut_rangeinclusive_max_panics() {
     let mut s = "hello".to_owned();
     let s: &mut str = &mut s;
-    &mut s[1...usize::max_value()];
+    &mut s[1..=usize::max_value()];
 }
 
 #[test]
@@ -391,13 +391,13 @@ fn test_str_get_maxinclusive() {
     let mut s = "hello".to_owned();
     {
         let s: &str = &s;
-        assert_eq!(s.get(...usize::max_value()), None);
-        assert_eq!(s.get(1...usize::max_value()), None);
+        assert_eq!(s.get(..=usize::max_value()), None);
+        assert_eq!(s.get(1..=usize::max_value()), None);
     }
     {
         let s: &mut str = &mut s;
-        assert_eq!(s.get(...usize::max_value()), None);
-        assert_eq!(s.get(1...usize::max_value()), None);
+        assert_eq!(s.get(..=usize::max_value()), None);
+        assert_eq!(s.get(1..=usize::max_value()), None);
     }
 }
 
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index 6aba18ddf49..ef6f5e10a72 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -456,9 +456,9 @@ fn test_splice_char_boundary() {
 #[test]
 fn test_splice_inclusive_range() {
     let mut v = String::from("12345");
-    v.splice(2...3, "789");
+    v.splice(2..=3, "789");
     assert_eq!(v, "127895");
-    v.splice(1...2, "A");
+    v.splice(1..=2, "A");
     assert_eq!(v, "1A895");
 }
 
@@ -473,7 +473,7 @@ fn test_splice_out_of_bounds() {
 #[should_panic]
 fn test_splice_inclusive_out_of_bounds() {
     let mut s = String::from("12345");
-    s.splice(5...5, "789");
+    s.splice(5..=5, "789");
 }
 
 #[test]
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 670ea8089fc..0e25da5bd30 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -537,27 +537,27 @@ fn test_drain_range() {
 #[test]
 fn test_drain_inclusive_range() {
     let mut v = vec!['a', 'b', 'c', 'd', 'e'];
-    for _ in v.drain(1...3) {
+    for _ in v.drain(1..=3) {
     }
     assert_eq!(v, &['a', 'e']);
 
-    let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
-    for _ in v.drain(1...5) {
+    let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
+    for _ in v.drain(1..=5) {
     }
     assert_eq!(v, &["0".to_string()]);
 
-    let mut v: Vec<String> = (0...5).map(|x| x.to_string()).collect();
-    for _ in v.drain(0...5) {
+    let mut v: Vec<String> = (0..=5).map(|x| x.to_string()).collect();
+    for _ in v.drain(0..=5) {
     }
     assert_eq!(v, Vec::<String>::new());
 
-    let mut v: Vec<_> = (0...5).map(|x| x.to_string()).collect();
-    for _ in v.drain(0...3) {
+    let mut v: Vec<_> = (0..=5).map(|x| x.to_string()).collect();
+    for _ in v.drain(0..=3) {
     }
     assert_eq!(v, &["4".to_string(), "5".to_string()]);
 
-    let mut v: Vec<_> = (0...1).map(|x| x.to_string()).collect();
-    for _ in v.drain(...0) {
+    let mut v: Vec<_> = (0..=1).map(|x| x.to_string()).collect();
+    for _ in v.drain(..=0) {
     }
     assert_eq!(v, &["1".to_string()]);
 }
@@ -572,7 +572,7 @@ fn test_drain_max_vec_size() {
 
     let mut v = Vec::<()>::with_capacity(usize::max_value());
     unsafe { v.set_len(usize::max_value()); }
-    for _ in v.drain(usize::max_value() - 1...usize::max_value() - 1) {
+    for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {
     }
     assert_eq!(v.len(), usize::max_value() - 1);
 }
@@ -581,7 +581,7 @@ fn test_drain_max_vec_size() {
 #[should_panic]
 fn test_drain_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
-    v.drain(5...5);
+    v.drain(5..=5);
 }
 
 #[test]
@@ -598,10 +598,10 @@ fn test_splice() {
 fn test_splice_inclusive_range() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    let t1: Vec<_> = v.splice(2...3, a.iter().cloned()).collect();
+    let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect();
     assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
     assert_eq!(t1, &[3, 4]);
-    let t2: Vec<_> = v.splice(1...2, Some(20)).collect();
+    let t2: Vec<_> = v.splice(1..=2, Some(20)).collect();
     assert_eq!(v, &[1, 20, 11, 12, 5]);
     assert_eq!(t2, &[2, 10]);
 }
@@ -619,7 +619,7 @@ fn test_splice_out_of_bounds() {
 fn test_splice_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(5...5, a.iter().cloned());
+    v.splice(5..=5, a.iter().cloned());
 }
 
 #[test]
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 7dd8895c1ae..725d3e15f4a 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1950,7 +1950,7 @@ impl<T> Vec<T> {
     /// assert_eq!(u, &[1, 2]);
     /// ```
     #[inline]
-    #[stable(feature = "vec_splice", since = "1.22.0")]
+    #[stable(feature = "vec_splice", since = "1.21.0")]
     pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter>
         where R: RangeArgument<usize>, I: IntoIterator<Item=T>
     {
@@ -2553,13 +2553,13 @@ impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
 /// [`splice()`]: struct.Vec.html#method.splice
 /// [`Vec`]: struct.Vec.html
 #[derive(Debug)]
-#[stable(feature = "vec_splice", since = "1.22.0")]
+#[stable(feature = "vec_splice", since = "1.21.0")]
 pub struct Splice<'a, I: Iterator + 'a> {
     drain: Drain<'a, I::Item>,
     replace_with: I,
 }
 
-#[stable(feature = "vec_splice", since = "1.22.0")]
+#[stable(feature = "vec_splice", since = "1.21.0")]
 impl<'a, I: Iterator> Iterator for Splice<'a, I> {
     type Item = I::Item;
 
@@ -2572,18 +2572,18 @@ impl<'a, I: Iterator> Iterator for Splice<'a, I> {
     }
 }
 
-#[stable(feature = "vec_splice", since = "1.22.0")]
+#[stable(feature = "vec_splice", since = "1.21.0")]
 impl<'a, I: Iterator> DoubleEndedIterator for Splice<'a, I> {
     fn next_back(&mut self) -> Option<Self::Item> {
         self.drain.next_back()
     }
 }
 
-#[stable(feature = "vec_splice", since = "1.22.0")]
+#[stable(feature = "vec_splice", since = "1.21.0")]
 impl<'a, I: Iterator> ExactSizeIterator for Splice<'a, I> {}
 
 
-#[stable(feature = "vec_splice", since = "1.22.0")]
+#[stable(feature = "vec_splice", since = "1.21.0")]
 impl<'a, I: Iterator> Drop for Splice<'a, I> {
     fn drop(&mut self) {
         // exhaust drain first
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index 00def2a1eac..6d64e9e303f 100644
--- a/src/liballoc/vec_deque.rs
+++ b/src/liballoc/vec_deque.rs
@@ -558,7 +558,7 @@ impl<T> VecDeque<T> {
             .and_then(|needed_cap| needed_cap.checked_next_power_of_two())
             .expect("capacity overflow");
 
-        if new_cap > self.capacity() {
+        if new_cap > old_cap {
             self.buf.reserve_exact(used_cap, new_cap - used_cap);
             unsafe {
                 self.handle_cap_increase(old_cap);
@@ -1973,6 +1973,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
         self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
         unsafe { Some(self.ring.get_unchecked(self.head)) }
     }
+
+    fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc
+    {
+        let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
+        accum = back.iter().rfold(accum, &mut f);
+        front.iter().rfold(accum, &mut f)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2058,6 +2066,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
             Some(&mut *(elem as *mut _))
         }
     }
+
+    fn rfold<Acc, F>(self, mut accum: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc
+    {
+        let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
+        accum = back.iter_mut().rfold(accum, &mut f);
+        front.iter_mut().rfold(accum, &mut f)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index 94700cf4475..4042c4d2d4e 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -19,7 +19,7 @@ libc = { path = "../rustc/libc_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.50"
+cc = "1.0"
 
 [features]
 debug = []
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index d89d3bcdb62..7dd85ddcc79 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -11,7 +11,7 @@
 #![deny(warnings)]
 
 extern crate build_helper;
-extern crate gcc;
+extern crate cc;
 
 use std::env;
 use std::path::PathBuf;
@@ -63,7 +63,7 @@ fn main() {
         _ => return,
     };
 
-    let compiler = gcc::Build::new().get_compiler();
+    let compiler = cc::Build::new().get_compiler();
     // only msvc returns None for ar so unwrap is okay
     let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
     let cflags = compiler.args()
@@ -150,7 +150,7 @@ fn main() {
     // sure the symbols are available.
     if target.contains("androideabi") {
         println!("cargo:rerun-if-changed=pthread_atfork_dummy.c");
-        gcc::Build::new()
+        cc::Build::new()
             .flag("-fvisibility=hidden")
             .file("pthread_atfork_dummy.c")
             .compile("libpthread_atfork_dummy.a");
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 827c6354c60..1f16f5b1df3 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -147,40 +147,131 @@ fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
     });
 }
 
-#[bench]
-fn bench_flat_map_sum(b: &mut Bencher) {
-    b.iter(|| -> i64 {
-        (0i64..1000).flat_map(|x| x..x+1000)
-            .map(black_box)
-            .sum()
-    });
+
+/// Helper to benchmark `sum` for iterators taken by value which
+/// can optimize `fold`, and by reference which cannot.
+macro_rules! bench_sums {
+    ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
+        #[bench]
+        fn $bench_sum(b: &mut Bencher) {
+            b.iter(|| -> i64 {
+                $iter.map(black_box).sum()
+            });
+        }
+
+        #[bench]
+        fn $bench_ref_sum(b: &mut Bencher) {
+            b.iter(|| -> i64 {
+                $iter.map(black_box).by_ref().sum()
+            });
+        }
+    }
 }
 
-#[bench]
-fn bench_flat_map_ref_sum(b: &mut Bencher) {
-    b.iter(|| -> i64 {
-        (0i64..1000).flat_map(|x| x..x+1000)
-            .map(black_box)
-            .by_ref()
-            .sum()
-    });
+bench_sums! {
+    bench_flat_map_sum,
+    bench_flat_map_ref_sum,
+    (0i64..1000).flat_map(|x| x..x+1000)
 }
 
-#[bench]
-fn bench_flat_map_chain_sum(b: &mut Bencher) {
-    b.iter(|| -> i64 {
-        (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
-            .map(black_box)
-            .sum()
-    });
+bench_sums! {
+    bench_flat_map_chain_sum,
+    bench_flat_map_chain_ref_sum,
+    (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
 }
 
-#[bench]
-fn bench_flat_map_chain_ref_sum(b: &mut Bencher) {
-    b.iter(|| -> i64 {
-        (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
-            .map(black_box)
-            .by_ref()
-            .sum()
-    });
+bench_sums! {
+    bench_enumerate_sum,
+    bench_enumerate_ref_sum,
+    (0i64..1000000).enumerate().map(|(i, x)| x * i as i64)
+}
+
+bench_sums! {
+    bench_enumerate_chain_sum,
+    bench_enumerate_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64)
+}
+
+bench_sums! {
+    bench_filter_sum,
+    bench_filter_ref_sum,
+    (0i64..1000000).filter(|x| x % 2 == 0)
+}
+
+bench_sums! {
+    bench_filter_chain_sum,
+    bench_filter_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+}
+
+bench_sums! {
+    bench_filter_map_sum,
+    bench_filter_map_ref_sum,
+    (0i64..1000000).filter_map(|x| x.checked_mul(x))
+}
+
+bench_sums! {
+    bench_filter_map_chain_sum,
+    bench_filter_map_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x))
+}
+
+bench_sums! {
+    bench_fuse_sum,
+    bench_fuse_ref_sum,
+    (0i64..1000000).fuse()
+}
+
+bench_sums! {
+    bench_fuse_chain_sum,
+    bench_fuse_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).fuse()
+}
+
+bench_sums! {
+    bench_inspect_sum,
+    bench_inspect_ref_sum,
+    (0i64..1000000).inspect(|_| {})
+}
+
+bench_sums! {
+    bench_inspect_chain_sum,
+    bench_inspect_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).inspect(|_| {})
+}
+
+bench_sums! {
+    bench_peekable_sum,
+    bench_peekable_ref_sum,
+    (0i64..1000000).peekable()
+}
+
+bench_sums! {
+    bench_peekable_chain_sum,
+    bench_peekable_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).peekable()
+}
+
+bench_sums! {
+    bench_skip_sum,
+    bench_skip_ref_sum,
+    (0i64..1000000).skip(1000)
+}
+
+bench_sums! {
+    bench_skip_chain_sum,
+    bench_skip_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).skip(1000)
+}
+
+bench_sums! {
+    bench_skip_while_sum,
+    bench_skip_while_ref_sum,
+    (0i64..1000000).skip_while(|&x| x < 1000)
+}
+
+bench_sums! {
+    bench_skip_while_chain_sum,
+    bench_skip_while_chain_ref_sum,
+    (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000)
 }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 6f86f8caad0..e012cbd76ff 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -456,7 +456,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
     /// assert_eq!(2, 1.max(2));
     /// assert_eq!(2, 2.max(2));
     /// ```
-    #[stable(feature = "ord_max_min", since = "1.22.0")]
+    #[stable(feature = "ord_max_min", since = "1.21.0")]
     fn max(self, other: Self) -> Self
     where Self: Sized {
         if other >= self { other } else { self }
@@ -472,7 +472,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
     /// assert_eq!(1, 1.min(2));
     /// assert_eq!(2, 2.min(2));
     /// ```
-    #[stable(feature = "ord_max_min", since = "1.22.0")]
+    #[stable(feature = "ord_max_min", since = "1.21.0")]
     fn min(self, other: Self) -> Self
     where Self: Sized {
         if self <= other { self } else { other }
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 6f3c3863fae..e815d72d366 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -48,8 +48,25 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use str::FromStr;
+use fmt;
 
+/// A type used as the error type for implementations of fallible conversion
+/// traits in cases where conversions cannot actually fail.
+///
+/// Because `Infallible` has no variants, a value of this type can never exist.
+/// It is used only to satisfy trait signatures that expect an error type, and
+/// signals to both the compiler and the user that the error case is impossible.
+#[unstable(feature = "try_from", issue = "33417")]
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub enum Infallible {}
+
+#[unstable(feature = "try_from", issue = "33417")]
+impl fmt::Display for Infallible {
+    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+        }
+    }
+}
 /// A cheap reference-to-reference conversion. Used to convert a value to a
 /// reference value within generic code.
 ///
@@ -417,6 +434,17 @@ impl<T, U> TryInto<U> for T where U: TryFrom<T>
     }
 }
 
+// Infallible conversions are semantically equivalent to fallible conversions
+// with an uninhabited error type.
+#[unstable(feature = "try_from", issue = "33417")]
+impl<T, U> TryFrom<U> for T where T: From<U> {
+    type Error = Infallible;
+
+    fn try_from(value: U) -> Result<Self, Self::Error> {
+        Ok(T::from(value))
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // CONCRETE IMPLS
 ////////////////////////////////////////////////////////////////////////////////
@@ -442,14 +470,3 @@ impl AsRef<str> for str {
         self
     }
 }
-
-// FromStr implies TryFrom<&str>
-#[unstable(feature = "try_from", issue = "33417")]
-impl<'a, T> TryFrom<&'a str> for T where T: FromStr
-{
-    type Error = <T as FromStr>::Err;
-
-    fn try_from(s: &'a str) -> Result<T, Self::Error> {
-        FromStr::from_str(s)
-    }
-}
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index cf6262bda97..6c251b9eb09 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -488,13 +488,14 @@ impl<'a> Display for Arguments<'a> {
 /// The origin is: Point { x: 0, y: 0 }
 /// ```
 ///
-/// There are a number of `debug_*` methods on `Formatter` to help you with manual
+/// There are a number of `debug_*` methods on [`Formatter`] to help you with manual
 /// implementations, such as [`debug_struct`][debug_struct].
 ///
 /// `Debug` implementations using either `derive` or the debug builder API
-/// on `Formatter` support pretty printing using the alternate flag: `{:#?}`.
+/// on [`Formatter`] support pretty printing using the alternate flag: `{:#?}`.
 ///
 /// [debug_struct]: ../../std/fmt/struct.Formatter.html#method.debug_struct
+/// [`Formatter`]: ../../std/fmt/struct.Formatter.html
 ///
 /// Pretty printing with `#?`:
 ///
@@ -1321,8 +1322,11 @@ impl<'a> Formatter<'a> {
         self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
     }
 
-    /// Creates a `DebugStruct` builder designed to assist with creation of
-    /// `fmt::Debug` implementations for structs.
+    /// Creates a [`DebugStruct`] builder designed to assist with creation of
+    /// [`fmt::Debug`] implementations for structs.
+    ///
+    /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.html
+    /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.html
     ///
     /// # Examples
     ///
@@ -1700,8 +1704,18 @@ impl<T: ?Sized + Debug> Debug for RefCell<T> {
                     .finish()
             }
             Err(_) => {
+                // The RefCell is mutably borrowed so we can't look at its value
+                // here. Show a placeholder instead.
+                struct BorrowedPlaceholder;
+
+                impl Debug for BorrowedPlaceholder {
+                    fn fmt(&self, f: &mut Formatter) -> Result {
+                        f.write_str("<borrowed>")
+                    }
+                }
+
                 f.debug_struct("RefCell")
-                    .field("value", &"<borrowed>")
+                    .field("value", &BorrowedPlaceholder)
                     .finish()
             }
         }
diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs
index 9a7914064fd..cb215a38e53 100644
--- a/src/libcore/internal_macros.rs
+++ b/src/libcore/internal_macros.rs
@@ -68,3 +68,22 @@ macro_rules! forward_ref_binop {
         }
     }
 }
+
+// implements "T op= &U", based on "T op= U"
+// where U is expected to be `Copy`able
+macro_rules! forward_ref_op_assign {
+    (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
+        forward_ref_op_assign!(impl $imp, $method for $t, $u,
+                #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
+    };
+    (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
+        #[$attr]
+        impl<'a> $imp<&'a $u> for $t {
+            #[inline]
+            fn $method(&mut self, other: &'a $u) {
+                $imp::$method(self, *other);
+            }
+        }
+    }
+}
+
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index edafd0ce2c2..e9e31065cf8 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -518,7 +518,7 @@ pub trait Iterator {
     ///       .for_each(|(i, x)| println!("{}:{}", i, x));
     /// ```
     #[inline]
-    #[stable(feature = "iterator_for_each", since = "1.22.0")]
+    #[stable(feature = "iterator_for_each", since = "1.21.0")]
     fn for_each<F>(self, mut f: F) where
         Self: Sized, F: FnMut(Self::Item),
     {
@@ -1337,7 +1337,7 @@ pub trait Iterator {
         (left, right)
     }
 
-    /// An iterator adaptor that applies a function, producing a single, final value.
+    /// An iterator method that applies a function, producing a single, final value.
     ///
     /// `fold()` takes two arguments: an initial value, and a closure with two
     /// arguments: an 'accumulator', and an element. The closure returns the value that
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index a596ffd6ae8..8d2521b053e 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -359,6 +359,12 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 
+    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, f)
+    }
+
     #[inline]
     fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
         where P: FnMut(&Self::Item) -> bool
@@ -379,6 +385,12 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
     #[inline]
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
 
+    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, f)
+    }
+
     fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
         where P: FnMut(&Self::Item) -> bool
     {
@@ -449,6 +461,12 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
     fn next_back(&mut self) -> Option<T> {
         self.it.next_back().cloned()
     }
+
+    fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.it.rfold(init, move |acc, elt| f(acc, elt.clone()))
+    }
 }
 
 #[stable(feature = "iter_cloned", since = "1.1.0")]
@@ -470,7 +488,7 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I>
 {}
 
 #[doc(hidden)]
-unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
+default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
     where I: TrustedRandomAccess<Item=&'a T>, T: Clone
 {
     unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
@@ -481,6 +499,18 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
     fn may_have_side_effect() -> bool { true }
 }
 
+#[doc(hidden)]
+unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
+    where I: TrustedRandomAccess<Item=&'a T>, T: Copy
+{
+    unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
+        *self.it.get_unchecked(i)
+    }
+
+    #[inline]
+    fn may_have_side_effect() -> bool { false }
+}
+
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
     where I: TrustedLen<Item=&'a T>,
@@ -528,7 +558,7 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
 #[unstable(feature = "fused", issue = "35602")]
 impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
 
-/// An adapter for stepping iterators by a custom amount.
+/// An iterator for stepping iterators by a custom amount.
 ///
 /// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
 /// its documentation for more.
@@ -761,6 +791,26 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
             ChainState::Back => self.b.next_back(),
         }
     }
+
+    fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc
+        where F: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut accum = init;
+        match self.state {
+            ChainState::Both | ChainState::Back => {
+                accum = self.b.rfold(accum, &mut f);
+            }
+            _ => { }
+        }
+        match self.state {
+            ChainState::Both | ChainState::Front => {
+                accum = self.a.rfold(accum, &mut f);
+            }
+            _ => { }
+        }
+        accum
+    }
+
 }
 
 // Note: *both* must be fused to handle double-ended iterators.
@@ -1094,6 +1144,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
     fn next_back(&mut self) -> Option<B> {
         self.iter.next_back().map(&mut self.f)
     }
+
+    fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
+        where G: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut f = self.f;
+        self.iter.rfold(init, move |acc, elt| g(acc, f(elt)))
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1193,6 +1250,18 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
         }
         count
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut predicate = self.predicate;
+        self.iter.fold(init, move |acc, item| if predicate(&item) {
+            fold(acc, item)
+        } else {
+            acc
+        })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1208,6 +1277,18 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
         }
         None
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut predicate = self.predicate;
+        self.iter.rfold(init, move |acc, item| if predicate(&item) {
+            fold(acc, item)
+        } else {
+            acc
+        })
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
@@ -1259,6 +1340,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut f = self.f;
+        self.iter.fold(init, move |acc, item| match f(item) {
+            Some(x) => fold(acc, x),
+            None => acc,
+        })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1274,6 +1366,17 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
         }
         None
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut f = self.f;
+        self.iter.rfold(init, move |acc, item| match f(item) {
+            Some(x) => fold(acc, x),
+            None => acc,
+        })
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
@@ -1338,6 +1441,19 @@ impl<I> Iterator for Enumerate<I> where I: Iterator {
     fn count(self) -> usize {
         self.iter.count()
     }
+
+    #[inline]
+    #[rustc_inherit_overflow_checks]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut count = self.count;
+        self.iter.fold(init, move |acc, item| {
+            let acc = fold(acc, (count, item));
+            count += 1;
+            acc
+        })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1353,6 +1469,19 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
             (self.count + len, a)
         })
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        // Can safely add and subtract the count, as `ExactSizeIterator` promises
+        // that the number of elements fits into a `usize`.
+        let mut count = self.count + self.iter.len();
+        self.iter.rfold(init, move |acc, item| {
+            count -= 1;
+            fold(acc, (count, item))
+        })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1464,6 +1593,18 @@ impl<I: Iterator> Iterator for Peekable<I> {
         let hi = hi.and_then(|x| x.checked_add(peek_len));
         (lo, hi)
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let acc = match self.peeked {
+            Some(None) => return init,
+            Some(Some(v)) => fold(init, v),
+            None => init,
+        };
+        self.iter.fold(acc, fold)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1572,6 +1713,19 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, mut init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if !self.flag {
+            match self.next() {
+                Some(v) => init = fold(init, v),
+                None => return init,
+            }
+        }
+        self.iter.fold(init, fold)
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
@@ -1712,6 +1866,19 @@ impl<I> Iterator for Skip<I> where I: Iterator {
 
         (lower, upper)
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if self.n > 0 {
+            // nth(n) skips n+1
+            if self.iter.nth(self.n - 1).is_none() {
+                return init;
+            }
+        }
+        self.iter.fold(init, fold)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1934,6 +2101,16 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
             }
         }
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.frontiter.into_iter()
+            .chain(self.iter.map(self.f).map(U::into_iter))
+            .chain(self.backiter)
+            .rfold(init, |acc, iter| iter.rfold(acc, &mut fold))
+    }
 }
 
 #[unstable(feature = "fused", issue = "35602")]
@@ -2011,6 +2188,17 @@ impl<I> Iterator for Fuse<I> where I: Iterator {
             self.iter.size_hint()
         }
     }
+
+    #[inline]
+    default fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if self.done {
+            init
+        } else {
+            self.iter.fold(init, fold)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2025,6 +2213,17 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
             next
         }
     }
+
+    #[inline]
+    default fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        if self.done {
+            init
+        } else {
+            self.iter.rfold(init, fold)
+        }
+    }
 }
 
 unsafe impl<I> TrustedRandomAccess for Fuse<I>
@@ -2065,6 +2264,13 @@ impl<I> Iterator for Fuse<I> where I: FusedIterator {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.fold(init, fold)
+    }
 }
 
 #[unstable(feature = "fused", reason = "recently added", issue = "35602")]
@@ -2075,6 +2281,13 @@ impl<I> DoubleEndedIterator for Fuse<I>
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
         self.iter.next_back()
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.iter.rfold(init, fold)
+    }
 }
 
 
@@ -2139,6 +2352,14 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) {
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.iter.size_hint()
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut f = self.f;
+        self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2150,6 +2371,14 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F>
         let next = self.iter.next_back();
         self.do_inspect(next)
     }
+
+    #[inline]
+    fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        let mut f = self.f;
+        self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) })
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 73d518b570a..e9aee4a4676 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -89,6 +89,7 @@ macro_rules! step_impl_unsigned {
             }
 
             #[inline]
+            #[allow(unreachable_patterns)]
             fn add_usize(&self, n: usize) -> Option<Self> {
                 match <$t>::try_from(n) {
                     Ok(n_as_t) => self.checked_add(n_as_t),
@@ -120,6 +121,7 @@ macro_rules! step_impl_signed {
             }
 
             #[inline]
+            #[allow(unreachable_patterns)]
             fn add_usize(&self, n: usize) -> Option<Self> {
                 match <$unsigned>::try_from(n) {
                     Ok(n_as_unsigned) => {
diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs
index 7ef50396c82..28236d193c3 100644
--- a/src/libcore/iter/traits.rs
+++ b/src/libcore/iter/traits.rs
@@ -415,6 +415,70 @@ pub trait DoubleEndedIterator: Iterator {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn next_back(&mut self) -> Option<Self::Item>;
 
+    /// An iterator method that reduces the iterator's elements to a single,
+    /// final value, starting from the back.
+    ///
+    /// This is the reverse version of [`fold()`]: it takes elements starting from
+    /// the back of the iterator.
+    ///
+    /// `rfold()` takes two arguments: an initial value, and a closure with two
+    /// arguments: an 'accumulator', and an element. The closure returns the value that
+    /// the accumulator should have for the next iteration.
+    ///
+    /// The initial value is the value the accumulator will have on the first
+    /// call.
+    ///
+    /// After applying this closure to every element of the iterator, `rfold()`
+    /// returns the accumulator.
+    ///
+    /// This operation is sometimes called 'reduce' or 'inject'.
+    ///
+    /// Folding is useful whenever you have a collection of something, and want
+    /// to produce a single value from it.
+    ///
+    /// [`fold()`]: trait.Iterator.html#method.fold
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iter_rfold)]
+    /// let a = [1, 2, 3];
+    ///
+    /// // the sum of all of the elements of a
+    /// let sum = a.iter()
+    ///            .rfold(0, |acc, &x| acc + x);
+    ///
+    /// assert_eq!(sum, 6);
+    /// ```
+    ///
+    /// This example builds a string, starting with an initial value
+    /// and continuing with each element from the back until the front:
+    ///
+    /// ```
+    /// #![feature(iter_rfold)]
+    /// let numbers = [1, 2, 3, 4, 5];
+    ///
+    /// let zero = "0".to_string();
+    ///
+    /// let result = numbers.iter().rfold(zero, |acc, &x| {
+    ///     format!("({} + {})", x, acc)
+    /// });
+    ///
+    /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
+    /// ```
+    #[inline]
+    #[unstable(feature = "iter_rfold", issue = "44705")]
+    fn rfold<B, F>(mut self, mut accum: B, mut f: F) -> B where
+        Self: Sized, F: FnMut(B, Self::Item) -> B,
+    {
+        while let Some(x) = self.next_back() {
+            accum = f(accum, x);
+        }
+        accum
+    }
+
     /// Searches for an element of an iterator from the right that satisfies a predicate.
     ///
     /// `rfind()` takes a closure that returns `true` or `false`. It applies
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index e8fd729b638..f56a9a40332 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -122,7 +122,7 @@ pub trait Sized {
 /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "unsize", issue = "27732")]
-#[lang="unsize"]
+#[lang = "unsize"]
 pub trait Unsize<T: ?Sized> {
     // Empty.
 }
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 34994dc3b70..c869054cee8 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -177,15 +177,59 @@ pub fn forget<T>(t: T) {
 
 /// Returns the size of a type in bytes.
 ///
-/// More specifically, this is the offset in bytes between successive
-/// items of the same type, including alignment padding.
+/// More specifically, this is the offset in bytes between successive elements
+/// in an array with that item type including alignment padding. Thus, for any
+/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`.
+///
+/// In general, the size of a type is not stable across compilations, but
+/// specific types such as primitives are.
+///
+/// The following table gives the size for primitives.
+///
+/// Type | size_of::\<Type>()
+/// ---- | ---------------
+/// () | 0
+/// u8 | 1
+/// u16 | 2
+/// u32 | 4
+/// u64 | 8
+/// i8 | 1
+/// i16 | 2
+/// i32 | 4
+/// i64 | 8
+/// f32 | 4
+/// f64 | 8
+/// char | 4
+///
+/// Furthermore, `usize` and `isize` have the same size.
+///
+/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have
+/// the same size. If `T` is Sized, all of those types have the same size as `usize`.
+///
+/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
+/// have the same size. Likewise for `*const T` and `*mut T`.
 ///
 /// # Examples
 ///
 /// ```
 /// use std::mem;
 ///
+/// // Some primitives
 /// assert_eq!(4, mem::size_of::<i32>());
+/// assert_eq!(8, mem::size_of::<f64>());
+/// assert_eq!(0, mem::size_of::<()>());
+///
+/// // Some arrays
+/// assert_eq!(8, mem::size_of::<[i32; 2]>());
+/// assert_eq!(12, mem::size_of::<[i32; 3]>());
+/// assert_eq!(0, mem::size_of::<[i32; 0]>());
+///
+///
+/// // Pointer size equality
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>());
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>());
+/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
+/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -358,7 +402,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// }
 /// ```
 #[inline]
-#[stable(feature = "needs_drop", since = "1.22.0")]
+#[stable(feature = "needs_drop", since = "1.21.0")]
 pub fn needs_drop<T>() -> bool {
     unsafe { intrinsics::needs_drop::<T>() }
 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index bf31deae7a6..85be8a08728 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -12,7 +12,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use convert::TryFrom;
+use convert::{Infallible, TryFrom};
 use fmt;
 use intrinsics;
 use str::FromStr;
@@ -2507,16 +2507,24 @@ impl fmt::Display for TryFromIntError {
     }
 }
 
+#[unstable(feature = "try_from", issue = "33417")]
+impl From<Infallible> for TryFromIntError {
+    fn from(infallible: Infallible) -> TryFromIntError {
+        match infallible {
+        }
+    }
+}
+
 // no possible bounds violation
 macro_rules! try_from_unbounded {
     ($source:ty, $($target:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
-            type Error = TryFromIntError;
+            type Error = Infallible;
 
             #[inline]
-            fn try_from(u: $source) -> Result<$target, TryFromIntError> {
-                Ok(u as $target)
+            fn try_from(value: $source) -> Result<Self, Self::Error> {
+                Ok(value as $target)
             }
         }
     )*}
@@ -2588,31 +2596,17 @@ macro_rules! rev {
 }
 
 /// intra-sign conversions
-try_from_unbounded!(u8, u8, u16, u32, u64, u128);
-try_from_unbounded!(u16, u16, u32, u64, u128);
-try_from_unbounded!(u32, u32, u64, u128);
-try_from_unbounded!(u64, u64, u128);
-try_from_unbounded!(u128, u128);
 try_from_upper_bounded!(u16, u8);
 try_from_upper_bounded!(u32, u16, u8);
 try_from_upper_bounded!(u64, u32, u16, u8);
 try_from_upper_bounded!(u128, u64, u32, u16, u8);
 
-try_from_unbounded!(i8, i8, i16, i32, i64, i128);
-try_from_unbounded!(i16, i16, i32, i64, i128);
-try_from_unbounded!(i32, i32, i64, i128);
-try_from_unbounded!(i64, i64, i128);
-try_from_unbounded!(i128, i128);
 try_from_both_bounded!(i16, i8);
 try_from_both_bounded!(i32, i16, i8);
 try_from_both_bounded!(i64, i32, i16, i8);
 try_from_both_bounded!(i128, i64, i32, i16, i8);
 
 // unsigned-to-signed
-try_from_unbounded!(u8, i16, i32, i64, i128);
-try_from_unbounded!(u16, i32, i64, i128);
-try_from_unbounded!(u32, i64, i128);
-try_from_unbounded!(u64, i128);
 try_from_upper_bounded!(u8, i8);
 try_from_upper_bounded!(u16, i8, i16);
 try_from_upper_bounded!(u32, i8, i16, i32);
@@ -2631,15 +2625,13 @@ try_from_both_bounded!(i64, u32, u16, u8);
 try_from_both_bounded!(i128, u64, u32, u16, u8);
 
 // usize/isize
-try_from_unbounded!(usize, usize);
 try_from_upper_bounded!(usize, isize);
 try_from_lower_bounded!(isize, usize);
-try_from_unbounded!(isize, isize);
 
 #[cfg(target_pointer_width = "16")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::TryFrom;
+    use convert::{Infallible, TryFrom};
 
     try_from_upper_bounded!(usize, u8);
     try_from_unbounded!(usize, u16, u32, u64, u128);
@@ -2651,21 +2643,21 @@ mod ptr_try_from_impls {
     try_from_both_bounded!(isize, i8);
     try_from_unbounded!(isize, i16, i32, i64, i128);
 
-    rev!(try_from_unbounded, usize, u8, u16);
+    rev!(try_from_unbounded, usize, u16);
     rev!(try_from_upper_bounded, usize, u32, u64, u128);
     rev!(try_from_lower_bounded, usize, i8, i16);
     rev!(try_from_both_bounded, usize, i32, i64, i128);
 
     rev!(try_from_unbounded, isize, u8);
     rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
-    rev!(try_from_unbounded, isize, i8, i16);
+    rev!(try_from_unbounded, isize, i16);
     rev!(try_from_both_bounded, isize, i32, i64, i128);
 }
 
 #[cfg(target_pointer_width = "32")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::TryFrom;
+    use convert::{Infallible, TryFrom};
 
     try_from_upper_bounded!(usize, u8, u16);
     try_from_unbounded!(usize, u32, u64, u128);
@@ -2677,21 +2669,21 @@ mod ptr_try_from_impls {
     try_from_both_bounded!(isize, i8, i16);
     try_from_unbounded!(isize, i32, i64, i128);
 
-    rev!(try_from_unbounded, usize, u8, u16, u32);
+    rev!(try_from_unbounded, usize, u16, u32);
     rev!(try_from_upper_bounded, usize, u64, u128);
     rev!(try_from_lower_bounded, usize, i8, i16, i32);
     rev!(try_from_both_bounded, usize, i64, i128);
 
     rev!(try_from_unbounded, isize, u8, u16);
     rev!(try_from_upper_bounded, isize, u32, u64, u128);
-    rev!(try_from_unbounded, isize, i8, i16, i32);
+    rev!(try_from_unbounded, isize, i16, i32);
     rev!(try_from_both_bounded, isize, i64, i128);
 }
 
 #[cfg(target_pointer_width = "64")]
 mod ptr_try_from_impls {
     use super::TryFromIntError;
-    use convert::TryFrom;
+    use convert::{Infallible, TryFrom};
 
     try_from_upper_bounded!(usize, u8, u16, u32);
     try_from_unbounded!(usize, u64, u128);
@@ -2703,14 +2695,14 @@ mod ptr_try_from_impls {
     try_from_both_bounded!(isize, i8, i16, i32);
     try_from_unbounded!(isize, i64, i128);
 
-    rev!(try_from_unbounded, usize, u8, u16, u32, u64);
+    rev!(try_from_unbounded, usize, u16, u32, u64);
     rev!(try_from_upper_bounded, usize, u128);
     rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
     rev!(try_from_both_bounded, usize, i128);
 
     rev!(try_from_unbounded, isize, u8, u16, u32);
     rev!(try_from_upper_bounded, isize, u64, u128);
-    rev!(try_from_unbounded, isize, i8, i16, i32, i64);
+    rev!(try_from_unbounded, isize, i16, i32, i64);
     rev!(try_from_both_bounded, isize, i128);
 }
 
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index acdf685e850..ae1b0b3ce11 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -36,6 +36,7 @@ macro_rules! sh_impl_signed {
                 *self = *self << other;
             }
         }
+        forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Shr<$f> for Wrapping<$t> {
@@ -58,6 +59,7 @@ macro_rules! sh_impl_signed {
                 *self = *self >> other;
             }
         }
+        forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
     )
 }
 
@@ -80,6 +82,7 @@ macro_rules! sh_impl_unsigned {
                 *self = *self << other;
             }
         }
+        forward_ref_op_assign! { impl ShlAssign, shl_assign for Wrapping<$t>, $f }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Shr<$f> for Wrapping<$t> {
@@ -98,6 +101,7 @@ macro_rules! sh_impl_unsigned {
                 *self = *self >> other;
             }
         }
+        forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
     )
 }
 
@@ -142,6 +146,7 @@ macro_rules! wrapping_impl {
                 *self = *self + other;
             }
         }
+        forward_ref_op_assign! { impl AddAssign, add_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Sub for Wrapping<$t> {
@@ -162,6 +167,7 @@ macro_rules! wrapping_impl {
                 *self = *self - other;
             }
         }
+        forward_ref_op_assign! { impl SubAssign, sub_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Mul for Wrapping<$t> {
@@ -182,6 +188,7 @@ macro_rules! wrapping_impl {
                 *self = *self * other;
             }
         }
+        forward_ref_op_assign! { impl MulAssign, mul_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_div", since = "1.3.0")]
         impl Div for Wrapping<$t> {
@@ -202,6 +209,7 @@ macro_rules! wrapping_impl {
                 *self = *self / other;
             }
         }
+        forward_ref_op_assign! { impl DivAssign, div_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_impls", since = "1.7.0")]
         impl Rem for Wrapping<$t> {
@@ -222,6 +230,7 @@ macro_rules! wrapping_impl {
                 *self = *self % other;
             }
         }
+        forward_ref_op_assign! { impl RemAssign, rem_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl Not for Wrapping<$t> {
@@ -254,6 +263,7 @@ macro_rules! wrapping_impl {
                 *self = *self ^ other;
             }
         }
+        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl BitOr for Wrapping<$t> {
@@ -274,6 +284,7 @@ macro_rules! wrapping_impl {
                 *self = *self | other;
             }
         }
+        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl BitAnd for Wrapping<$t> {
@@ -294,6 +305,7 @@ macro_rules! wrapping_impl {
                 *self = *self & other;
             }
         }
+        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Wrapping<$t>, Wrapping<$t> }
 
         #[stable(feature = "wrapping_neg", since = "1.10.0")]
         impl Neg for Wrapping<$t> {
diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs
index 62007caedd3..8b3d662a6db 100644
--- a/src/libcore/ops/arith.rs
+++ b/src/libcore/ops/arith.rs
@@ -662,6 +662,8 @@ macro_rules! add_assign_impl {
             #[rustc_inherit_overflow_checks]
             fn add_assign(&mut self, other: $t) { *self += other }
         }
+
+        forward_ref_op_assign! { impl AddAssign, add_assign for $t, $t }
     )+)
 }
 
@@ -713,6 +715,8 @@ macro_rules! sub_assign_impl {
             #[rustc_inherit_overflow_checks]
             fn sub_assign(&mut self, other: $t) { *self -= other }
         }
+
+        forward_ref_op_assign! { impl SubAssign, sub_assign for $t, $t }
     )+)
 }
 
@@ -755,6 +759,8 @@ macro_rules! mul_assign_impl {
             #[rustc_inherit_overflow_checks]
             fn mul_assign(&mut self, other: $t) { *self *= other }
         }
+
+        forward_ref_op_assign! { impl MulAssign, mul_assign for $t, $t }
     )+)
 }
 
@@ -796,6 +802,8 @@ macro_rules! div_assign_impl {
             #[inline]
             fn div_assign(&mut self, other: $t) { *self /= other }
         }
+
+        forward_ref_op_assign! { impl DivAssign, div_assign for $t, $t }
     )+)
 }
 
@@ -841,6 +849,8 @@ macro_rules! rem_assign_impl {
             #[inline]
             fn rem_assign(&mut self, other: $t) { *self %= other }
         }
+
+        forward_ref_op_assign! { impl RemAssign, rem_assign for $t, $t }
     )+)
 }
 
diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs
index 0bc5e554cb3..7ac5fc4debf 100644
--- a/src/libcore/ops/bit.rs
+++ b/src/libcore/ops/bit.rs
@@ -593,6 +593,8 @@ macro_rules! bitand_assign_impl {
             #[inline]
             fn bitand_assign(&mut self, other: $t) { *self &= other }
         }
+
+        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t }
     )+)
 }
 
@@ -638,6 +640,8 @@ macro_rules! bitor_assign_impl {
             #[inline]
             fn bitor_assign(&mut self, other: $t) { *self |= other }
         }
+
+        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t }
     )+)
 }
 
@@ -683,6 +687,8 @@ macro_rules! bitxor_assign_impl {
             #[inline]
             fn bitxor_assign(&mut self, other: $t) { *self ^= other }
         }
+
+        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t }
     )+)
 }
 
@@ -729,6 +735,8 @@ macro_rules! shl_assign_impl {
                 *self <<= other
             }
         }
+
+        forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f }
     )
 }
 
@@ -793,6 +801,8 @@ macro_rules! shr_assign_impl {
                 *self >>= other
             }
         }
+
+        forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f }
     )
 }
 
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index 463a50491a8..3f573f7c7eb 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -241,9 +241,9 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
     }
 }
 
-/// An range bounded inclusively below and above (`start...end`).
+/// An range bounded inclusively below and above (`start..=end`).
 ///
-/// The `RangeInclusive` `start...end` contains all values with `x >= start`
+/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
 /// and `x <= end`.
 ///
 /// # Examples
@@ -251,12 +251,12 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
 /// ```
 /// #![feature(inclusive_range,inclusive_range_syntax)]
 ///
-/// assert_eq!((3...5), std::ops::RangeInclusive { start: 3, end: 5 });
-/// assert_eq!(3 + 4 + 5, (3...5).sum());
+/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
+/// assert_eq!(3 + 4 + 5, (3..=5).sum());
 ///
 /// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ ...2], [0,1,2  ]);
-/// assert_eq!(arr[1...2], [  1,2  ]);  // RangeInclusive
+/// assert_eq!(arr[ ..=2], [0,1,2  ]);
+/// assert_eq!(arr[1..=2], [  1,2  ]);  // RangeInclusive
 /// ```
 #[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
@@ -276,7 +276,7 @@ pub struct RangeInclusive<Idx> {
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "{:?}...{:?}", self.start, self.end)
+        write!(fmt, "{:?}..={:?}", self.start, self.end)
     }
 }
 
@@ -289,32 +289,32 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     /// ```
     /// #![feature(range_contains,inclusive_range_syntax)]
     ///
-    /// assert!(!(3...5).contains(2));
-    /// assert!( (3...5).contains(3));
-    /// assert!( (3...5).contains(4));
-    /// assert!( (3...5).contains(5));
-    /// assert!(!(3...5).contains(6));
+    /// assert!(!(3..=5).contains(2));
+    /// assert!( (3..=5).contains(3));
+    /// assert!( (3..=5).contains(4));
+    /// assert!( (3..=5).contains(5));
+    /// assert!(!(3..=5).contains(6));
     ///
-    /// assert!( (3...3).contains(3));
-    /// assert!(!(3...2).contains(3));
+    /// assert!( (3..=3).contains(3));
+    /// assert!(!(3..=2).contains(3));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         self.start <= item && item <= self.end
     }
 }
 
-/// A range only bounded inclusively above (`...end`).
+/// A range only bounded inclusively above (`..=end`).
 ///
-/// The `RangeToInclusive` `...end` contains all values with `x <= end`.
+/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
 /// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
 ///
 /// # Examples
 ///
-/// The `...end` syntax is a `RangeToInclusive`:
+/// The `..=end` syntax is a `RangeToInclusive`:
 ///
 /// ```
 /// #![feature(inclusive_range,inclusive_range_syntax)]
-/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
+/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
 /// ```
 ///
 /// It does not have an [`IntoIterator`] implementation, so you can't use it in a
@@ -325,7 +325,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 ///
 /// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
 /// // std::iter::Iterator` is not satisfied
-/// for i in ...5 {
+/// for i in ..=5 {
 ///     // ...
 /// }
 /// ```
@@ -337,8 +337,8 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
 /// #![feature(inclusive_range_syntax)]
 ///
 /// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ ...2], [0,1,2  ]);  // RangeToInclusive
-/// assert_eq!(arr[1...2], [  1,2  ]);
+/// assert_eq!(arr[ ..=2], [0,1,2  ]);  // RangeToInclusive
+/// assert_eq!(arr[1..=2], [  1,2  ]);
 /// ```
 ///
 /// [`IntoIterator`]: ../iter/trait.Iterator.html
@@ -357,7 +357,7 @@ pub struct RangeToInclusive<Idx> {
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "...{:?}", self.end)
+        write!(fmt, "..={:?}", self.end)
     }
 }
 
@@ -370,9 +370,9 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
     /// ```
     /// #![feature(range_contains,inclusive_range_syntax)]
     ///
-    /// assert!( (...5).contains(-1_000_000_000));
-    /// assert!( (...5).contains(5));
-    /// assert!(!(...5).contains(6));
+    /// assert!( (..=5).contains(-1_000_000_000));
+    /// assert!( (..=5).contains(5));
+    /// assert!(!(..=5).contains(6));
     /// ```
     pub fn contains(&self, item: Idx) -> bool {
         (item <= self.end)
diff --git a/src/libcore/ops/unsize.rs b/src/libcore/ops/unsize.rs
index 58da290cfb6..cd896859b16 100644
--- a/src/libcore/ops/unsize.rs
+++ b/src/libcore/ops/unsize.rs
@@ -42,7 +42,7 @@ use marker::Unsize;
 /// [unsize]: ../marker/trait.Unsize.html
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "coerce_unsized", issue = "27732")]
-#[lang="coerce_unsized"]
+#[lang = "coerce_unsized"]
 pub trait CoerceUnsized<T> {
     // Empty.
 }
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 138e04c7737..980ea551f08 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -146,7 +146,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use iter::{FromIterator, FusedIterator, TrustedLen};
-use mem;
+use {mem, ops};
 
 // Note that this is not a lang item per se, but it has a hidden dependency on
 // `Iterator`, which is one. The compiler assumes that the `next` method of
@@ -1123,3 +1123,29 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
         }
     }
 }
+
+/// The error type that results from applying the try operator (`?`) to a `None` value. If you wish
+/// to allow `x?` (where `x` is an `Option<T>`) to be converted into your error type, you can
+/// implement `impl From<NoneError>` for `YourErrorType`. In that case, `x?` within a function that
+/// returns `Result<_, YourErrorType>` will translate a `None` value into an `Err` result.
+#[unstable(feature = "try_trait", issue = "42327")]
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+pub struct NoneError;
+
+#[unstable(feature = "try_trait", issue = "42327")]
+impl<T> ops::Try for Option<T> {
+    type Ok = T;
+    type Error = NoneError;
+
+    fn into_result(self) -> Result<T, NoneError> {
+        self.ok_or(NoneError)
+    }
+
+    fn from_ok(v: T) -> Self {
+        Some(v)
+    }
+
+    fn from_error(_: NoneError) -> Self {
+        None
+    }
+}
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 4041a3760e5..34d31044653 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -56,7 +56,7 @@ pub use intrinsics::write_bytes;
 /// This has all the same safety problems as `ptr::read` with respect to
 /// invalid pointers, types, and double drops.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
-#[lang="drop_in_place"]
+#[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
 pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     // Code here does not matter - this is replaced by the
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index dacc014955a..ae243f3f246 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -16,6 +16,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+// FIXME: after next stage0, change RangeInclusive { ... } back to ..=
+use ops::RangeInclusive;
+
 // How this module is organized.
 //
 // The library infrastructure for slices is fairly messy. There's
@@ -1044,32 +1047,32 @@ impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        (0...self.end).get(slice)
+        (RangeInclusive { start: 0, end: self.end }).get(slice)
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        (0...self.end).get_mut(slice)
+        (RangeInclusive { start: 0, end: self.end }).get_mut(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
-        (0...self.end).get_unchecked(slice)
+        (RangeInclusive { start: 0, end: self.end }).get_unchecked(slice)
     }
 
     #[inline]
     unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).get_unchecked_mut(slice)
+        (RangeInclusive { start: 0, end: self.end }).get_unchecked_mut(slice)
     }
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        (0...self.end).index(slice)
+        (RangeInclusive { start: 0, end: self.end }).index(slice)
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (0...self.end).index_mut(slice)
+        (RangeInclusive { start: 0, end: self.end }).index_mut(slice)
     }
 }
 
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index c24cdb30bad..0af9fcf0a3d 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -18,9 +18,9 @@ use self::pattern::Pattern;
 use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 
 use char;
-use convert::TryFrom;
 use fmt;
-use iter::{Map, Cloned, FusedIterator};
+use iter::{Map, Cloned, FusedIterator, TrustedLen};
+use iter_private::TrustedRandomAccess;
 use slice::{self, SliceIndex};
 use mem;
 
@@ -818,6 +818,17 @@ impl<'a> ExactSizeIterator for Bytes<'a> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a> FusedIterator for Bytes<'a> {}
 
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<'a> TrustedLen for Bytes<'a> {}
+
+#[doc(hidden)]
+unsafe impl<'a> TrustedRandomAccess for Bytes<'a> {
+    unsafe fn get_unchecked(&mut self, i: usize) -> u8 {
+        self.0.get_unchecked(i)
+    }
+    fn may_have_side_effect() -> bool { false }
+}
+
 /// This macro generates a Clone impl for string pattern API
 /// wrapper types of the form X<'a, P>
 macro_rules! derive_pattern_clone {
@@ -1399,9 +1410,6 @@ Section: Comparing strings
 */
 
 /// Bytewise slice equality
-/// NOTE: This function is (ab)used in rustc::middle::trans::_match
-/// to compare &[u8] byte slices that are not necessarily valid UTF-8.
-#[lang = "str_eq"]
 #[inline]
 fn eq_slice(a: &str, b: &str) -> bool {
     a.as_bytes() == b.as_bytes()
@@ -2189,7 +2197,7 @@ pub trait StrExt {
     #[stable(feature = "core", since = "1.6.0")]
     fn is_empty(&self) -> bool;
     #[stable(feature = "core", since = "1.6.0")]
-    fn parse<'a, T: TryFrom<&'a str>>(&'a self) -> Result<T, T::Error>;
+    fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
 }
 
 // truncate `&str` to length at most equal to `max`
@@ -2509,9 +2517,7 @@ impl StrExt for str {
     fn is_empty(&self) -> bool { self.len() == 0 }
 
     #[inline]
-    fn parse<'a, T>(&'a self) -> Result<T, T::Error> where T: TryFrom<&'a str> {
-        T::try_from(self)
-    }
+    fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 3dd08e69710..465d31b5f49 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -926,10 +926,24 @@ macro_rules! atomic_int {
      $stable_cxchg:meta,
      $stable_debug:meta,
      $stable_access:meta,
+     $s_int_type:expr, $int_ref:expr,
      $int_type:ident $atomic_type:ident $atomic_init:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
-        /// This type has the same in-memory representation as the underlying integer type.
+        /// This type has the same in-memory representation as the underlying
+        /// integer type, [`
+        #[doc = $s_int_type]
+        /// `](
+        #[doc = $int_ref]
+        /// ). For more about the differences between atomic types and
+        /// non-atomic types, please see the [module-level documentation].
+        ///
+        /// Please note that examples are shared between atomic variants of
+        /// primitive integer types, so it's normal that they are all
+        /// demonstrating [`AtomicIsize`].
+        ///
+        /// [module-level documentation]: index.html
+        /// [`AtomicIsize`]: struct.AtomicIsize.html
         #[$stable]
         pub struct $atomic_type {
             v: UnsafeCell<$int_type>,
@@ -1339,6 +1353,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "i8", "../../../std/primitive.i8.html",
     i8 AtomicI8 ATOMIC_I8_INIT
 }
 #[cfg(target_has_atomic = "8")]
@@ -1348,6 +1363,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "u8", "../../../std/primitive.u8.html",
     u8 AtomicU8 ATOMIC_U8_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1357,6 +1373,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "i16", "../../../std/primitive.i16.html",
     i16 AtomicI16 ATOMIC_I16_INIT
 }
 #[cfg(target_has_atomic = "16")]
@@ -1366,6 +1383,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "u16", "../../../std/primitive.u16.html",
     u16 AtomicU16 ATOMIC_U16_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1375,6 +1393,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "i32", "../../../std/primitive.i32.html",
     i32 AtomicI32 ATOMIC_I32_INIT
 }
 #[cfg(target_has_atomic = "32")]
@@ -1384,6 +1403,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "u32", "../../../std/primitive.u32.html",
     u32 AtomicU32 ATOMIC_U32_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1393,6 +1413,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "i64", "../../../std/primitive.i64.html",
     i64 AtomicI64 ATOMIC_I64_INIT
 }
 #[cfg(target_has_atomic = "64")]
@@ -1402,6 +1423,7 @@ atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
+    "u64", "../../../std/primitive.u64.html",
     u64 AtomicU64 ATOMIC_U64_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1411,6 +1433,7 @@ atomic_int!{
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
+    "isize", "../../../std/primitive.isize.html",
     isize AtomicIsize ATOMIC_ISIZE_INIT
 }
 #[cfg(target_has_atomic = "ptr")]
@@ -1420,6 +1443,7 @@ atomic_int!{
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
+    "usize", "../../../std/primitive.usize.html",
     usize AtomicUsize ATOMIC_USIZE_INIT
 }
 
@@ -1752,7 +1776,7 @@ pub fn fence(order: Ordering) {
 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 /// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt
 #[inline]
-#[stable(feature = "compiler_fences", since = "1.22.0")]
+#[stable(feature = "compiler_fences", since = "1.21.0")]
 pub fn compiler_fence(order: Ordering) {
     unsafe {
         match order {
diff --git a/src/libcore/tests/char.rs b/src/libcore/tests/char.rs
index 7c3b90c8153..4e10ceac878 100644
--- a/src/libcore/tests/char.rs
+++ b/src/libcore/tests/char.rs
@@ -32,7 +32,6 @@ fn test_convert() {
 #[test]
 fn test_from_str() {
     assert_eq!(char::from_str("a").unwrap(), 'a');
-    assert_eq!(char::try_from("a").unwrap(), 'a');
     assert_eq!(char::from_str("\0").unwrap(), '\0');
     assert_eq!(char::from_str("\u{D7FF}").unwrap(), '\u{d7FF}');
     assert!(char::from_str("").is_err());
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 59ae30de452..f8c6fc5c8fa 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -249,6 +249,25 @@ fn test_filter_map() {
 }
 
 #[test]
+fn test_filter_map_fold() {
+    let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    let ys = [0*0, 2*2, 4*4, 6*6, 8*8];
+    let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None });
+    let i = it.fold(0, |i, x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+
+    let it = xs.iter().filter_map(|&x| if x % 2 == 0 { Some(x*x) } else { None });
+    let i = it.rfold(ys.len(), |i, x| {
+        assert_eq!(x, ys[i - 1]);
+        i - 1
+    });
+    assert_eq!(i, 0);
+}
+
+#[test]
 fn test_iterator_enumerate() {
     let xs = [0, 1, 2, 3, 4, 5];
     let it = xs.iter().enumerate();
@@ -282,7 +301,31 @@ fn test_iterator_enumerate_nth() {
 #[test]
 fn test_iterator_enumerate_count() {
     let xs = [0, 1, 2, 3, 4, 5];
-    assert_eq!(xs.iter().count(), 6);
+    assert_eq!(xs.iter().enumerate().count(), 6);
+}
+
+#[test]
+fn test_iterator_enumerate_fold() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().enumerate();
+    // steal a couple to get an interesting offset
+    assert_eq!(it.next(), Some((0, &0)));
+    assert_eq!(it.next(), Some((1, &1)));
+    let i = it.fold(2, |i, (j, &x)| {
+        assert_eq!(i, j);
+        assert_eq!(x, xs[j]);
+        i + 1
+    });
+    assert_eq!(i, xs.len());
+
+    let mut it = xs.iter().enumerate();
+    assert_eq!(it.next(), Some((0, &0)));
+    let i = it.rfold(xs.len() - 1, |i, (j, &x)| {
+        assert_eq!(i, j);
+        assert_eq!(x, xs[j]);
+        i - 1
+    });
+    assert_eq!(i, 0);
 }
 
 #[test]
@@ -292,6 +335,25 @@ fn test_iterator_filter_count() {
 }
 
 #[test]
+fn test_iterator_filter_fold() {
+    let xs = [0, 1, 2, 3, 4, 5, 6, 7, 8];
+    let ys = [0, 2, 4, 6, 8];
+    let it = xs.iter().filter(|&&x| x % 2 == 0);
+    let i = it.fold(0, |i, &x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+
+    let it = xs.iter().filter(|&&x| x % 2 == 0);
+    let i = it.rfold(ys.len(), |i, &x| {
+        assert_eq!(x, ys[i - 1]);
+        i - 1
+    });
+    assert_eq!(i, 0);
+}
+
+#[test]
 fn test_iterator_peekable() {
     let xs = vec![0, 1, 2, 3, 4, 5];
     let mut it = xs.iter().cloned().peekable();
@@ -381,6 +443,18 @@ fn test_iterator_peekable_last() {
     assert_eq!(it.last(), None);
 }
 
+#[test]
+fn test_iterator_peekable_fold() {
+    let xs = [0, 1, 2, 3, 4, 5];
+    let mut it = xs.iter().peekable();
+    assert_eq!(it.peek(), Some(&&0));
+    let i = it.fold(0, |i, &x| {
+        assert_eq!(x, xs[i]);
+        i + 1
+    });
+    assert_eq!(i, xs.len());
+}
+
 /// This is an iterator that follows the Iterator contract,
 /// but it is not fused. After having returned None once, it will start
 /// producing elements if .next() is called again.
@@ -471,6 +545,26 @@ fn test_iterator_skip_while() {
 }
 
 #[test]
+fn test_iterator_skip_while_fold() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+    let ys = [15, 16, 17, 19];
+    let it = xs.iter().skip_while(|&x| *x < 15);
+    let i = it.fold(0, |i, &x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+
+    let mut it = xs.iter().skip_while(|&x| *x < 15);
+    assert_eq!(it.next(), Some(&ys[0])); // process skips before folding
+    let i = it.fold(1, |i, &x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+}
+
+#[test]
 fn test_iterator_skip() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
     let ys = [13, 15, 16, 17, 19, 20, 30];
@@ -567,6 +661,26 @@ fn test_iterator_skip_last() {
 }
 
 #[test]
+fn test_iterator_skip_fold() {
+    let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+    let ys = [13, 15, 16, 17, 19, 20, 30];
+    let it = xs.iter().skip(5);
+    let i = it.fold(0, |i, &x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+
+    let mut it = xs.iter().skip(5);
+    assert_eq!(it.next(), Some(&ys[0])); // process skips before folding
+    let i = it.fold(1, |i, &x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+}
+
+#[test]
 fn test_iterator_take() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
     let ys = [0, 1, 2, 3, 5];
@@ -661,13 +775,22 @@ fn test_iterator_flat_map_fold() {
     let xs = [0, 3, 6];
     let ys = [1, 2, 3, 4, 5, 6, 7];
     let mut it = xs.iter().flat_map(|&x| x..x+3);
-    it.next();
-    it.next_back();
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next_back(), Some(8));
     let i = it.fold(0, |i, x| {
         assert_eq!(x, ys[i]);
         i + 1
     });
     assert_eq!(i, ys.len());
+
+    let mut it = xs.iter().flat_map(|&x| x..x+3);
+    assert_eq!(it.next(), Some(0));
+    assert_eq!(it.next_back(), Some(8));
+    let i = it.rfold(ys.len(), |i, x| {
+        assert_eq!(x, ys[i - 1]);
+        i - 1
+    });
+    assert_eq!(i, 0);
 }
 
 #[test]
@@ -685,6 +808,32 @@ fn test_inspect() {
 }
 
 #[test]
+fn test_inspect_fold() {
+    let xs = [1, 2, 3, 4];
+    let mut n = 0;
+    {
+        let it = xs.iter().inspect(|_| n += 1);
+        let i = it.fold(0, |i, &x| {
+            assert_eq!(x, xs[i]);
+            i + 1
+        });
+        assert_eq!(i, xs.len());
+    }
+    assert_eq!(n, xs.len());
+
+    let mut n = 0;
+    {
+        let it = xs.iter().inspect(|_| n += 1);
+        let i = it.rfold(xs.len(), |i, &x| {
+            assert_eq!(x, xs[i - 1]);
+            i - 1
+        });
+        assert_eq!(i, 0);
+    }
+    assert_eq!(n, xs.len());
+}
+
+#[test]
 fn test_cycle() {
     let cycle_len = 3;
     let it = (0..).step_by(1).take(cycle_len).cycle();
@@ -1094,21 +1243,21 @@ fn test_range() {
 
 #[test]
 fn test_range_inclusive_exhaustion() {
-    let mut r = 10...10;
+    let mut r = 10..=10;
     assert_eq!(r.next(), Some(10));
-    assert_eq!(r, 1...0);
+    assert_eq!(r, 1..=0);
 
-    let mut r = 10...10;
+    let mut r = 10..=10;
     assert_eq!(r.next_back(), Some(10));
-    assert_eq!(r, 1...0);
+    assert_eq!(r, 1..=0);
 
-    let mut r = 10...12;
+    let mut r = 10..=12;
     assert_eq!(r.nth(2), Some(12));
-    assert_eq!(r, 1...0);
+    assert_eq!(r, 1..=0);
 
-    let mut r = 10...12;
+    let mut r = 10..=12;
     assert_eq!(r.nth(5), None);
-    assert_eq!(r, 1...0);
+    assert_eq!(r, 1..=0);
 
 }
 
@@ -1145,20 +1294,20 @@ fn test_range_from_nth() {
 
 #[test]
 fn test_range_inclusive_nth() {
-    assert_eq!((10...15).nth(0), Some(10));
-    assert_eq!((10...15).nth(1), Some(11));
-    assert_eq!((10...15).nth(5), Some(15));
-    assert_eq!((10...15).nth(6), None);
+    assert_eq!((10..=15).nth(0), Some(10));
+    assert_eq!((10..=15).nth(1), Some(11));
+    assert_eq!((10..=15).nth(5), Some(15));
+    assert_eq!((10..=15).nth(6), None);
 
-    let mut r = 10_u8...20;
+    let mut r = 10_u8..=20;
     assert_eq!(r.nth(2), Some(12));
-    assert_eq!(r, 13...20);
+    assert_eq!(r, 13..=20);
     assert_eq!(r.nth(2), Some(15));
-    assert_eq!(r, 16...20);
+    assert_eq!(r, 16..=20);
     assert_eq!(r.is_empty(), false);
     assert_eq!(r.nth(10), None);
     assert_eq!(r.is_empty(), true);
-    assert_eq!(r, 1...0);  // We may not want to document/promise this detail
+    assert_eq!(r, 1..=0);  // We may not want to document/promise this detail
 }
 
 #[test]
@@ -1242,6 +1391,31 @@ fn test_fuse_count() {
 }
 
 #[test]
+fn test_fuse_fold() {
+    let xs = [0, 1, 2];
+    let it = xs.iter(); // `FusedIterator`
+    let i = it.fuse().fold(0, |i, &x| {
+        assert_eq!(x, xs[i]);
+        i + 1
+    });
+    assert_eq!(i, xs.len());
+
+    let it = xs.iter(); // `FusedIterator`
+    let i = it.fuse().rfold(xs.len(), |i, &x| {
+        assert_eq!(x, xs[i - 1]);
+        i - 1
+    });
+    assert_eq!(i, 0);
+
+    let it = xs.iter().scan((), |_, &x| Some(x)); // `!FusedIterator`
+    let i = it.fuse().fold(0, |i, x| {
+        assert_eq!(x, xs[i]);
+        i + 1
+    });
+    assert_eq!(i, xs.len());
+}
+
+#[test]
 fn test_once() {
     let mut it = once(42);
     assert_eq!(it.next(), Some(42));
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 47995597a0a..afc5de7b0ee 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -25,6 +25,7 @@
 #![feature(inclusive_range)]
 #![feature(inclusive_range_syntax)]
 #![feature(iter_rfind)]
+#![feature(iter_rfold)]
 #![feature(nonzero)]
 #![feature(rand)]
 #![feature(raw)]
@@ -38,6 +39,7 @@
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_from)]
+#![feature(try_trait)]
 #![feature(unique)]
 
 #![feature(const_atomic_bool_new)]
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index 400d53ce51a..7eb5ff98857 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::convert::TryFrom;
+use core::convert::{TryFrom, TryInto};
 use core::cmp::PartialEq;
 use core::fmt::Debug;
 use core::marker::Copy;
+use core::num::TryFromIntError;
 use core::ops::{Add, Sub, Mul, Div, Rem};
 use core::option::Option;
 use core::option::Option::{Some, None};
@@ -134,6 +135,13 @@ fn test_empty() {
     assert_eq!("".parse::<u8>().ok(), None);
 }
 
+#[test]
+fn test_infallible_try_from_int_error() {
+    let func = |x: i8| -> Result<i32, TryFromIntError> { Ok(x.try_into()?) };
+
+    assert!(func(0).is_ok());
+}
+
 macro_rules! test_impl_from {
     ($fn_name: ident, $Small: ty, $Large: ty) => {
         #[test]
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 6bac55575fb..22109e28edd 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -270,3 +270,30 @@ fn test_cloned() {
     assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
     assert_eq!(opt_ref_ref.cloned().cloned(), Some(1));
 }
+
+#[test]
+fn test_try() {
+    fn try_option_some() -> Option<u8> {
+        let val = Some(1)?;
+        Some(val)
+    }
+    assert_eq!(try_option_some(), Some(1));
+
+    fn try_option_none() -> Option<u8> {
+        let val = None?;
+        Some(val)
+    }
+    assert_eq!(try_option_none(), None);
+
+    fn try_option_ok() -> Result<u8, NoneError> {
+        let val = Some(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_option_ok(), Ok(1));
+
+    fn try_option_err() -> Result<u8, NoneError> {
+        let val = None?;
+        Ok(val)
+    }
+    assert_eq!(try_option_err(), Err(NoneError));
+}
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index 4c5f19dee12..ce41bde8342 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use core::option::*;
+
 fn op1() -> Result<isize, &'static str> { Ok(666) }
 fn op2() -> Result<isize, &'static str> { Err("sadface") }
 
@@ -202,3 +204,30 @@ pub fn test_unwrap_or_default() {
     assert_eq!(op1().unwrap_or_default(), 666);
     assert_eq!(op2().unwrap_or_default(), 0);
 }
+
+#[test]
+fn test_try() {
+    fn try_result_some() -> Option<u8> {
+        let val = Ok(1)?;
+        Some(val)
+    }
+    assert_eq!(try_result_some(), Some(1));
+
+    fn try_result_none() -> Option<u8> {
+        let val = Err(NoneError)?;
+        Some(val)
+    }
+    assert_eq!(try_result_none(), None);
+
+    fn try_result_ok() -> Result<u8, u8> {
+        let val = Ok(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_result_ok(), Ok(1));
+
+    fn try_result_err() -> Result<u8, u8> {
+        let val = Err(1)?;
+        Ok(val)
+    }
+    assert_eq!(try_result_err(), Err(1));
+}
diff --git a/src/liblibc b/src/liblibc
-Subproject 95848f9622deccc9cbadcd5d3a4faef01a90ead
+Subproject 44e4018e1a37716286ec98cb5b7dd7d33ecaf94
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 07e933985a0..2c540c8de8f 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -509,6 +509,7 @@ impl TokenTree {
             Dot => op!('.'),
             DotDot => joint!('.', Dot),
             DotDotDot => joint!('.', DotDot),
+            DotDotEq => joint!('.', DotEq),
             Comma => op!(','),
             Semi => op!(';'),
             Colon => op!(':'),
@@ -531,6 +532,7 @@ impl TokenTree {
                 })
             }
 
+            DotEq => unreachable!(),
             OpenDelim(..) | CloseDelim(..) => unreachable!(),
             Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
         };
diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs
index 0db2b86b15f..8c1f6bfc11a 100644
--- a/src/libproc_macro/quote.rs
+++ b/src/libproc_macro/quote.rs
@@ -202,8 +202,8 @@ impl Quote for Token {
 
         gen_match! {
             Eq, Lt, Le, EqEq, Ne, Ge, Gt, AndAnd, OrOr, Not, Tilde, At, Dot, DotDot, DotDotDot,
-            Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar, Question,
-            Underscore;
+            DotDotEq, Comma, Semi, Colon, ModSep, RArrow, LArrow, FatArrow, Pound, Dollar,
+            Question, Underscore;
 
             Token::OpenDelim(delim) => quote!(rt::token::OpenDelim((quote delim))),
             Token::CloseDelim(delim) => quote!(rt::token::CloseDelim((quote delim))),
diff --git a/src/libprofiler_builtins/Cargo.toml b/src/libprofiler_builtins/Cargo.toml
index a60db313679..eb31f5730d1 100644
--- a/src/libprofiler_builtins/Cargo.toml
+++ b/src/libprofiler_builtins/Cargo.toml
@@ -15,4 +15,4 @@ doc = false
 core = { path = "../libcore" }
 
 [build-dependencies]
-gcc = "0.3.50"
+cc = "1.0"
diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs
index 41e92b33475..8508b2dae2c 100644
--- a/src/libprofiler_builtins/build.rs
+++ b/src/libprofiler_builtins/build.rs
@@ -12,14 +12,14 @@
 //!
 //! See the build.rs for libcompiler_builtins crate for details.
 
-extern crate gcc;
+extern crate cc;
 
 use std::env;
 use std::path::Path;
 
 fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
-    let cfg = &mut gcc::Build::new();
+    let cfg = &mut cc::Build::new();
 
     let mut profile_sources = vec!["GCDAProfiling.c",
                                    "InstrProfiling.c",
diff --git a/src/librustc/README.md b/src/librustc/README.md
index 59d346db4af..87de284d011 100644
--- a/src/librustc/README.md
+++ b/src/librustc/README.md
@@ -37,7 +37,7 @@ incremental improves that may change.)
 
 The dependency structure of these crates is roughly a diamond:
 
-````
+```
                   rustc_driver
                 /      |       \
               /        |         \
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index b4cb39a034b..7a78765365d 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -60,7 +60,7 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use hir::def_id::{CrateNum, DefId, DefIndex};
+use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
 
@@ -80,14 +80,28 @@ macro_rules! erase {
     ($x:tt) => ({})
 }
 
-macro_rules! anon_attr_to_bool {
-    (anon) => (true)
+macro_rules! is_anon_attr {
+    (anon) => (true);
+    ($attr:ident) => (false);
+}
+
+macro_rules! is_input_attr {
+    (input) => (true);
+    ($attr:ident) => (false);
+}
+
+macro_rules! contains_anon_attr {
+    ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false});
+}
+
+macro_rules! contains_input_attr {
+    ($($attr:ident),*) => ({$(is_input_attr!($attr) | )* false});
 }
 
 macro_rules! define_dep_nodes {
     (<$tcx:tt>
     $(
-        [$($anon:ident)*]
+        [$($attr:ident),* ]
         $variant:ident $(( $($tuple_arg:tt),* ))*
                        $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })*
       ,)*
@@ -105,7 +119,9 @@ macro_rules! define_dep_nodes {
                 match *self {
                     $(
                         DepKind :: $variant => {
-                            $(return !anon_attr_to_bool!($anon);)*
+                            if contains_anon_attr!($($attr),*) {
+                                return false;
+                            }
 
                             // tuple args
                             $({
@@ -126,15 +142,20 @@ macro_rules! define_dep_nodes {
                 }
             }
 
-            #[allow(unreachable_code)]
             #[inline]
-            pub fn is_anon<$tcx>(&self) -> bool {
+            pub fn is_anon(&self) -> bool {
                 match *self {
                     $(
-                        DepKind :: $variant => {
-                            $(return anon_attr_to_bool!($anon);)*
-                            false
-                        }
+                        DepKind :: $variant => { contains_anon_attr!($($attr),*) }
+                    )*
+                }
+            }
+
+            #[inline]
+            pub fn is_input(&self) -> bool {
+                match *self {
+                    $(
+                        DepKind :: $variant => { contains_input_attr!($($attr),*) }
                     )*
                 }
             }
@@ -366,6 +387,17 @@ impl DefId {
     }
 }
 
+impl DepKind {
+    #[inline]
+    pub fn fingerprint_needed_for_crate_hash(self) -> bool {
+        match self {
+            DepKind::HirBody |
+            DepKind::Krate => true,
+            _ => false,
+        }
+    }
+}
+
 define_dep_nodes!( <'tcx>
     // Represents the `Krate` as a whole (the `hir::Krate` value) (as
     // distinct from the krate module). This is basically a hash of
@@ -378,18 +410,17 @@ define_dep_nodes!( <'tcx>
     // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain
     // access to the krate, but you must remember to add suitable
     // edges yourself for the individual items that you read.
-    [] Krate,
-
-    // Represents the HIR node with the given node-id
-    [] Hir(DefId),
+    [input] Krate,
 
     // Represents the body of a function or method. The def-id is that of the
     // function/method.
-    [] HirBody(DefId),
+    [input] HirBody(DefId),
+
+    // Represents the HIR node with the given node-id
+    [input] Hir(DefId),
 
-    // Represents the metadata for a given HIR node, typically found
-    // in an extern crate.
-    [] MetaData(DefId),
+    // 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.
@@ -414,6 +445,7 @@ define_dep_nodes!( <'tcx>
     [] BorrowCheckKrate,
     [] BorrowCheck(DefId),
     [] MirBorrowCheck(DefId),
+    [] UnsafetyViolations(DefId),
 
     [] RvalueCheck(DefId),
     [] Reachability,
@@ -529,7 +561,7 @@ define_dep_nodes!( <'tcx>
     [] ExternCrate(DefId),
     [] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
-    [] InScopeTraits(DefIndex),
+    [input] InScopeTraits(DefIndex),
     [] ModuleExports(DefId),
     [] IsSanitizerRuntime(CrateNum),
     [] IsProfilerRuntime(CrateNum),
@@ -647,6 +679,22 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIndex,
     }
 }
 
+impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (CrateNum,) {
+    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+
+    fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
+        let def_id = DefId {
+            krate: self.0,
+            index: CRATE_DEF_INDEX,
+        };
+        tcx.def_path_hash(def_id).0
+    }
+
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        tcx.crate_name(self.0).as_str().to_string()
+    }
+}
+
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
     const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
 
diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs
index 809d1dfcf60..b12db11cb6a 100644
--- a/src/librustc/dep_graph/edges.rs
+++ b/src/librustc/dep_graph/edges.rs
@@ -17,7 +17,7 @@ use std::mem;
 use super::{DepGraphQuery, DepKind, DepNode};
 use super::debug::EdgeFilter;
 
-pub struct DepGraphEdges {
+pub(super) struct DepGraphEdges {
     nodes: Vec<DepNode>,
     indices: FxHashMap<DepNode, DepNodeIndex>,
     edges: FxHashSet<(DepNodeIndex, DepNodeIndex)>,
@@ -31,8 +31,8 @@ pub struct DepGraphEdges {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DepNodeIndex {
-    index: u32
+pub(super) struct DepNodeIndex {
+    index: u32,
 }
 
 impl DepNodeIndex {
@@ -123,6 +123,7 @@ impl DepGraphEdges {
             reads
         } = popped_node {
             debug_assert_eq!(node, key);
+            debug_assert!(!node.kind.is_input() || reads.is_empty());
 
             let target_id = self.get_or_create_node(node);
 
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 7679b7e7971..d9770db9d69 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHashingContextProvider};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use session::config::OutputType;
 use std::cell::{Ref, RefCell};
+use std::hash::Hash;
 use std::rc::Rc;
 use util::common::{ProfileQueriesMsg, profq_msg};
 
@@ -22,17 +24,56 @@ use super::dep_node::{DepNode, DepKind, WorkProductId};
 use super::query::DepGraphQuery;
 use super::raii;
 use super::safe::DepGraphSafe;
-use super::edges::{DepGraphEdges, DepNodeIndex};
+use super::edges::{self, DepGraphEdges};
+use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
+use super::prev::PreviousDepGraph;
 
 #[derive(Clone)]
 pub struct DepGraph {
-    data: Option<Rc<DepGraphData>>
+    data: Option<Rc<DepGraphData>>,
+
+    // At the moment we are using DepNode as key here. In the future it might
+    // be possible to use an IndexVec<DepNodeIndex, _> here. At the moment there
+    // are a few problems with that:
+    // - Some fingerprints are needed even if incr. comp. is disabled -- yet
+    //   we need to have a dep-graph to generate DepNodeIndices.
+    // - The architecture is still in flux and it's not clear what how to best
+    //   implement things.
+    fingerprints: Rc<RefCell<FxHashMap<DepNode, Fingerprint>>>
+}
+
+/// As a temporary measure, while transitioning to the new DepGraph
+/// implementation, we maintain the old and the new dep-graph encoding in
+/// parallel, so a DepNodeIndex actually contains two indices, one for each
+/// version.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DepNodeIndex {
+    legacy: edges::DepNodeIndex,
+    new: DepNodeIndexNew,
+}
+
+impl DepNodeIndex {
+    pub const INVALID: DepNodeIndex = DepNodeIndex {
+        legacy: edges::DepNodeIndex::INVALID,
+        new: DepNodeIndexNew::INVALID,
+    };
 }
 
 struct DepGraphData {
-    /// The actual graph data.
+    /// The old, initial encoding of the dependency graph. This will soon go
+    /// away.
     edges: RefCell<DepGraphEdges>,
 
+    /// The new encoding of the dependency graph, optimized for red/green
+    /// tracking. The `current` field is the dependency graph of only the
+    /// current compilation session: We don't merge the previous dep-graph into
+    /// current one anymore.
+    current: RefCell<CurrentDepGraph>,
+
+    /// The dep-graph from the previous compilation session. It contains all
+    /// nodes and edges as well as all fingerprints of nodes that have them.
+    previous: PreviousDepGraph,
+
     /// When we load, there may be `.o` files, cached mir, or other such
     /// things available to us. If we find that they are not dirty, we
     /// load the path to the file storing those work-products here into
@@ -46,18 +87,25 @@ struct DepGraphData {
 }
 
 impl DepGraph {
-    pub fn new(enabled: bool) -> DepGraph {
+
+    pub fn new(prev_graph: PreviousDepGraph) -> DepGraph {
         DepGraph {
-            data: if enabled {
-                Some(Rc::new(DepGraphData {
-                    previous_work_products: RefCell::new(FxHashMap()),
-                    work_products: RefCell::new(FxHashMap()),
-                    edges: RefCell::new(DepGraphEdges::new()),
-                    dep_node_debug: RefCell::new(FxHashMap()),
-                }))
-            } else {
-                None
-            }
+            data: Some(Rc::new(DepGraphData {
+                previous_work_products: RefCell::new(FxHashMap()),
+                work_products: RefCell::new(FxHashMap()),
+                edges: RefCell::new(DepGraphEdges::new()),
+                dep_node_debug: RefCell::new(FxHashMap()),
+                current: RefCell::new(CurrentDepGraph::new()),
+                previous: prev_graph,
+            })),
+            fingerprints: Rc::new(RefCell::new(FxHashMap())),
+        }
+    }
+
+    pub fn new_disabled() -> DepGraph {
+        DepGraph {
+            data: None,
+            fingerprints: Rc::new(RefCell::new(FxHashMap())),
         }
     }
 
@@ -72,7 +120,8 @@ impl DepGraph {
     }
 
     pub fn in_ignore<'graph>(&'graph self) -> Option<raii::IgnoreTask<'graph>> {
-        self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges))
+        self.data.as_ref().map(|data| raii::IgnoreTask::new(&data.edges,
+                                                            &data.current))
     }
 
     pub fn with_ignore<OP,R>(&self, op: OP) -> R
@@ -120,6 +169,7 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_task(key);
+            data.current.borrow_mut().push_task(key);
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
             };
@@ -135,15 +185,36 @@ impl DepGraph {
             if cfg!(debug_assertions) {
                 profq_msg(ProfileQueriesMsg::TaskEnd)
             };
-            let dep_node_index = data.edges.borrow_mut().pop_task(key);
+
+            let dep_node_index_legacy = data.edges.borrow_mut().pop_task(key);
+            let dep_node_index_new = data.current.borrow_mut().pop_task(key);
 
             let mut stable_hasher = StableHasher::new();
             result.hash_stable(&mut hcx, &mut stable_hasher);
-            let _: Fingerprint = stable_hasher.finish();
 
-            (result, dep_node_index)
+            assert!(self.fingerprints
+                        .borrow_mut()
+                        .insert(key, stable_hasher.finish())
+                        .is_none());
+
+            (result, DepNodeIndex {
+                legacy: dep_node_index_legacy,
+                new: dep_node_index_new,
+            })
         } else {
-            (task(cx, arg), DepNodeIndex::INVALID)
+            if key.kind.fingerprint_needed_for_crate_hash() {
+                let mut hcx = cx.create_stable_hashing_context();
+                let result = task(cx, arg);
+                let mut stable_hasher = StableHasher::new();
+                result.hash_stable(&mut hcx, &mut stable_hasher);
+                assert!(self.fingerprints
+                            .borrow_mut()
+                            .insert(key, stable_hasher.finish())
+                            .is_none());
+                (result, DepNodeIndex::INVALID)
+            } else {
+                (task(cx, arg), DepNodeIndex::INVALID)
+            }
         }
     }
 
@@ -154,9 +225,14 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_anon_task();
+            data.current.borrow_mut().push_anon_task();
             let result = op();
-            let dep_node = data.edges.borrow_mut().pop_anon_task(dep_kind);
-            (result, dep_node)
+            let dep_node_index_legacy = data.edges.borrow_mut().pop_anon_task(dep_kind);
+            let dep_node_index_new = data.current.borrow_mut().pop_anon_task(dep_kind);
+            (result, DepNodeIndex {
+                legacy: dep_node_index_legacy,
+                new: dep_node_index_new,
+            })
         } else {
             (op(), DepNodeIndex::INVALID)
         }
@@ -166,13 +242,21 @@ impl DepGraph {
     pub fn read(&self, v: DepNode) {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().read(v);
+
+            let mut current = data.current.borrow_mut();
+            if let Some(&dep_node_index_new) = current.node_to_node_index.get(&v) {
+                current.read_index(dep_node_index_new);
+            } else {
+                bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
+            }
         }
     }
 
     #[inline]
     pub fn read_index(&self, v: DepNodeIndex) {
         if let Some(ref data) = self.data {
-            data.edges.borrow_mut().read_index(v);
+            data.edges.borrow_mut().read_index(v.legacy);
+            data.current.borrow_mut().read_index(v.new);
         }
     }
 
@@ -187,12 +271,12 @@ impl DepGraph {
         self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
     }
 
-    pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
-        if let Some(ref data) = self.data {
-            data.edges.borrow_mut().add_node(node)
-        } else {
-            DepNodeIndex::INVALID
-        }
+    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        self.fingerprints.borrow()[dep_node]
+    }
+
+    pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
     }
 
     /// Indicates that a previous work product exists for `v`. This is
@@ -261,6 +345,44 @@ impl DepGraph {
     pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
         self.data.as_ref().and_then(|t| t.dep_node_debug.borrow().get(&dep_node).cloned())
     }
+
+    pub fn serialize(&self) -> SerializedDepGraph {
+        let fingerprints = self.fingerprints.borrow();
+        let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
+
+        let nodes: IndexVec<_, _> = current_dep_graph.nodes.iter().map(|dep_node| {
+            let fingerprint = fingerprints.get(dep_node)
+                                          .cloned()
+                                          .unwrap_or(Fingerprint::zero());
+            (*dep_node, fingerprint)
+        }).collect();
+
+        let total_edge_count: usize = current_dep_graph.edges.iter()
+                                                             .map(|v| v.len())
+                                                             .sum();
+
+        let mut edge_list_indices = IndexVec::with_capacity(nodes.len());
+        let mut edge_list_data = Vec::with_capacity(total_edge_count);
+
+        for (current_dep_node_index, edges) in current_dep_graph.edges.iter_enumerated() {
+            let start = edge_list_data.len() as u32;
+            // This should really just be a memcpy :/
+            edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex(i.index)));
+            let end = edge_list_data.len() as u32;
+
+            debug_assert_eq!(current_dep_node_index.index(), edge_list_indices.len());
+            edge_list_indices.push((start, end));
+        }
+
+        debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize);
+        debug_assert_eq!(edge_list_data.len(), total_edge_count);
+
+        SerializedDepGraph {
+            nodes,
+            edge_list_indices,
+            edge_list_data,
+        }
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
@@ -305,3 +427,174 @@ pub struct WorkProduct {
     /// Saved files associated with this CGU
     pub saved_files: Vec<(OutputType, String)>,
 }
+
+pub(super) struct CurrentDepGraph {
+    nodes: IndexVec<DepNodeIndexNew, DepNode>,
+    edges: IndexVec<DepNodeIndexNew, Vec<DepNodeIndexNew>>,
+    node_to_node_index: FxHashMap<DepNode, DepNodeIndexNew>,
+
+    task_stack: Vec<OpenTask>,
+}
+
+impl CurrentDepGraph {
+    fn new() -> CurrentDepGraph {
+        CurrentDepGraph {
+            nodes: IndexVec::new(),
+            edges: IndexVec::new(),
+            node_to_node_index: FxHashMap(),
+            task_stack: Vec::new(),
+        }
+    }
+
+    pub(super) fn push_ignore(&mut self) {
+        self.task_stack.push(OpenTask::Ignore);
+    }
+
+    pub(super) fn pop_ignore(&mut self) {
+        let popped_node = self.task_stack.pop().unwrap();
+        debug_assert_eq!(popped_node, OpenTask::Ignore);
+    }
+
+    pub(super) fn push_task(&mut self, key: DepNode) {
+        self.task_stack.push(OpenTask::Regular {
+            node: key,
+            reads: Vec::new(),
+            read_set: FxHashSet(),
+        });
+    }
+
+    pub(super) fn pop_task(&mut self, key: DepNode) -> DepNodeIndexNew {
+        let popped_node = self.task_stack.pop().unwrap();
+
+        if let OpenTask::Regular {
+            node,
+            read_set: _,
+            reads
+        } = popped_node {
+            debug_assert_eq!(node, key);
+            self.alloc_node(node, reads)
+        } else {
+            bug!("pop_task() - Expected regular task to be popped")
+        }
+    }
+
+    fn push_anon_task(&mut self) {
+        self.task_stack.push(OpenTask::Anon {
+            reads: Vec::new(),
+            read_set: FxHashSet(),
+        });
+    }
+
+    fn pop_anon_task(&mut self, kind: DepKind) -> DepNodeIndexNew {
+        let popped_node = self.task_stack.pop().unwrap();
+
+        if let OpenTask::Anon {
+            read_set: _,
+            reads
+        } = popped_node {
+            let mut fingerprint = Fingerprint::zero();
+            let mut hasher = StableHasher::new();
+
+            for &read in reads.iter() {
+                let read_dep_node = self.nodes[read];
+
+                ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);
+
+                // Fingerprint::combine() is faster than sending Fingerprint
+                // through the StableHasher (at least as long as StableHasher
+                // is so slow).
+                fingerprint = fingerprint.combine(read_dep_node.hash);
+            }
+
+            fingerprint = fingerprint.combine(hasher.finish());
+
+            let target_dep_node = DepNode {
+                kind,
+                hash: fingerprint,
+            };
+
+            if let Some(&index) = self.node_to_node_index.get(&target_dep_node) {
+                return index;
+            }
+
+            self.alloc_node(target_dep_node, reads)
+        } else {
+            bug!("pop_anon_task() - Expected anonymous task to be popped")
+        }
+    }
+
+    fn read_index(&mut self, source: DepNodeIndexNew) {
+        match self.task_stack.last_mut() {
+            Some(&mut OpenTask::Regular {
+                ref mut reads,
+                ref mut read_set,
+                node: _,
+            }) => {
+                if read_set.insert(source) {
+                    reads.push(source);
+                }
+            }
+            Some(&mut OpenTask::Anon {
+                ref mut reads,
+                ref mut read_set,
+            }) => {
+                if read_set.insert(source) {
+                    reads.push(source);
+                }
+            }
+            Some(&mut OpenTask::Ignore) | None => {
+                // ignore
+            }
+        }
+    }
+
+    fn alloc_node(&mut self,
+                  dep_node: DepNode,
+                  edges: Vec<DepNodeIndexNew>)
+                  -> DepNodeIndexNew {
+        debug_assert_eq!(self.edges.len(), self.nodes.len());
+        debug_assert_eq!(self.node_to_node_index.len(), self.nodes.len());
+        debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
+        let dep_node_index = DepNodeIndexNew::new(self.nodes.len());
+        self.nodes.push(dep_node);
+        self.node_to_node_index.insert(dep_node, dep_node_index);
+        self.edges.push(edges);
+        dep_node_index
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub(super) struct DepNodeIndexNew {
+    index: u32,
+}
+
+impl Idx for DepNodeIndexNew {
+    fn new(v: usize) -> DepNodeIndexNew {
+        assert!((v & 0xFFFF_FFFF) == v);
+        DepNodeIndexNew { index: v as u32 }
+    }
+
+    fn index(self) -> usize {
+        self.index as usize
+    }
+}
+
+impl DepNodeIndexNew {
+    const INVALID: DepNodeIndexNew = DepNodeIndexNew {
+        index: ::std::u32::MAX,
+    };
+}
+
+#[derive(Clone, Debug, PartialEq)]
+enum OpenTask {
+    Regular {
+        node: DepNode,
+        reads: Vec<DepNodeIndexNew>,
+        read_set: FxHashSet<DepNodeIndexNew>,
+    },
+    Anon {
+        reads: Vec<DepNodeIndexNew>,
+        read_set: FxHashSet<DepNodeIndexNew>,
+    },
+    Ignore,
+}
diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs
index ac0c88ced93..cd77e06bdd6 100644
--- a/src/librustc/dep_graph/mod.rs
+++ b/src/librustc/dep_graph/mod.rs
@@ -13,19 +13,17 @@ mod dep_node;
 mod dep_tracking_map;
 mod edges;
 mod graph;
+mod prev;
 mod query;
 mod raii;
 mod safe;
+mod serialized;
 
 pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
-pub use self::dep_node::DepNode;
-pub use self::dep_node::WorkProductId;
-pub use self::graph::DepGraph;
-pub use self::graph::WorkProduct;
-pub use self::edges::DepNodeIndex;
+pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId};
+pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex};
+pub use self::prev::PreviousDepGraph;
 pub use self::query::DepGraphQuery;
 pub use self::safe::AssertDepGraphSafe;
 pub use self::safe::DepGraphSafe;
-pub use self::raii::DepTask;
-
-pub use self::dep_node::{DepKind, DepConstructor};
+pub use self::serialized::SerializedDepGraph;
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
new file mode 100644
index 00000000000..882ca0414cc
--- /dev/null
+++ b/src/librustc/dep_graph/prev.rs
@@ -0,0 +1,46 @@
+// 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 ich::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use super::dep_node::DepNode;
+use super::serialized::{SerializedDepGraph, SerializedDepNodeIndex};
+
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct PreviousDepGraph {
+    data: SerializedDepGraph,
+    index: FxHashMap<DepNode, SerializedDepNodeIndex>,
+}
+
+impl PreviousDepGraph {
+    pub fn new(data: SerializedDepGraph) -> PreviousDepGraph {
+        let index: FxHashMap<_, _> = data.nodes
+            .iter_enumerated()
+            .map(|(idx, &(dep_node, _))| (dep_node, idx))
+            .collect();
+        PreviousDepGraph { data, index }
+    }
+
+    pub fn with_edges_from<F>(&self, dep_node: &DepNode, mut f: F)
+    where
+        F: FnMut(&(DepNode, Fingerprint)),
+    {
+        let node_index = self.index[dep_node];
+        self.data
+            .edge_targets_from(node_index)
+            .into_iter()
+            .for_each(|&index| f(&self.data.nodes[index]));
+    }
+
+    pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
+        let node_index = self.index[dep_node];
+        self.data.nodes[node_index].1
+    }
+}
diff --git a/src/librustc/dep_graph/raii.rs b/src/librustc/dep_graph/raii.rs
index ce261ca68e8..6e9e4f4a18b 100644
--- a/src/librustc/dep_graph/raii.rs
+++ b/src/librustc/dep_graph/raii.rs
@@ -8,50 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::DepNode;
 use super::edges::DepGraphEdges;
+use super::graph::CurrentDepGraph;
 
 use std::cell::RefCell;
 
-pub struct DepTask<'graph> {
-    graph: &'graph RefCell<DepGraphEdges>,
-    key: DepNode,
-}
-
-impl<'graph> DepTask<'graph> {
-    pub fn new(graph: &'graph RefCell<DepGraphEdges>,
-               key: DepNode)
-               -> DepTask<'graph> {
-        graph.borrow_mut().push_task(key);
-        DepTask {
-            graph,
-            key,
-        }
-    }
-}
-
-impl<'graph> Drop for DepTask<'graph> {
-    fn drop(&mut self) {
-        self.graph.borrow_mut().pop_task(self.key);
-    }
-}
-
 pub struct IgnoreTask<'graph> {
-    graph: &'graph RefCell<DepGraphEdges>,
+    legacy_graph: &'graph RefCell<DepGraphEdges>,
+    new_graph: &'graph RefCell<CurrentDepGraph>,
 }
 
 impl<'graph> IgnoreTask<'graph> {
-    pub fn new(graph: &'graph RefCell<DepGraphEdges>) -> IgnoreTask<'graph> {
-        graph.borrow_mut().push_ignore();
+    pub(super) fn new(legacy_graph: &'graph RefCell<DepGraphEdges>,
+                      new_graph: &'graph RefCell<CurrentDepGraph>)
+                      -> IgnoreTask<'graph> {
+        legacy_graph.borrow_mut().push_ignore();
+        new_graph.borrow_mut().push_ignore();
         IgnoreTask {
-            graph
+            legacy_graph,
+            new_graph,
         }
     }
 }
 
 impl<'graph> Drop for IgnoreTask<'graph> {
     fn drop(&mut self) {
-        self.graph.borrow_mut().pop_ignore();
+        self.legacy_graph.borrow_mut().pop_ignore();
+        self.new_graph.borrow_mut().pop_ignore();
     }
 }
 
diff --git a/src/librustc/dep_graph/serialized.rs b/src/librustc/dep_graph/serialized.rs
new file mode 100644
index 00000000000..6110c270086
--- /dev/null
+++ b/src/librustc/dep_graph/serialized.rs
@@ -0,0 +1,63 @@
+// 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.
+
+//! The data that we will serialize and deserialize.
+
+use dep_graph::DepNode;
+use ich::Fingerprint;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+/// The index of a DepNode in the SerializedDepGraph::nodes array.
+#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Debug,
+         RustcEncodable, RustcDecodable)]
+pub struct SerializedDepNodeIndex(pub u32);
+
+impl Idx for SerializedDepNodeIndex {
+    #[inline]
+    fn new(idx: usize) -> Self {
+        assert!(idx <= ::std::u32::MAX as usize);
+        SerializedDepNodeIndex(idx as u32)
+    }
+
+    #[inline]
+    fn index(self) -> usize {
+        self.0 as usize
+    }
+}
+
+/// Data for use when recompiling the **current crate**.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct SerializedDepGraph {
+    /// The set of all DepNodes in the graph
+    pub nodes: IndexVec<SerializedDepNodeIndex, (DepNode, Fingerprint)>,
+    /// For each DepNode, stores the list of edges originating from that
+    /// DepNode. Encoded as a [start, end) pair indexing into edge_list_data,
+    /// which holds the actual DepNodeIndices of the target nodes.
+    pub edge_list_indices: IndexVec<SerializedDepNodeIndex, (u32, u32)>,
+    /// A flattened list of all edge targets in the graph. Edge sources are
+    /// implicit in edge_list_indices.
+    pub edge_list_data: Vec<SerializedDepNodeIndex>,
+}
+
+impl SerializedDepGraph {
+
+    pub fn new() -> SerializedDepGraph {
+        SerializedDepGraph {
+            nodes: IndexVec::new(),
+            edge_list_indices: IndexVec::new(),
+            edge_list_data: Vec::new(),
+        }
+    }
+
+    pub fn edge_targets_from(&self, source: SerializedDepNodeIndex) -> &[SerializedDepNodeIndex] {
+        let targets = self.edge_list_indices[source];
+        &self.edge_list_data[targets.0 as usize..targets.1 as usize]
+    }
+}
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 4d21e5e0f47..26f56ffacae 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -479,40 +479,6 @@ fn main() {
 ```
 "##,
 
-E0133: r##"
-Unsafe code was used outside of an unsafe function or block.
-
-Erroneous code example:
-
-```compile_fail,E0133
-unsafe fn f() { return; } // This is the unsafe code
-
-fn main() {
-    f(); // error: call to unsafe function requires unsafe function or block
-}
-```
-
-Using unsafe functionality is potentially dangerous and disallowed by safety
-checks. Examples:
-
-* Dereferencing raw pointers
-* Calling functions via FFI
-* Calling functions marked unsafe
-
-These safety checks can be relaxed for a section of the code by wrapping the
-unsafe instructions with an `unsafe` block. For instance:
-
-```
-unsafe fn f() { return; }
-
-fn main() {
-    unsafe { f(); } // ok!
-}
-```
-
-See also https://doc.rust-lang.org/book/first-edition/unsafe.html
-"##,
-
 // This shouldn't really ever trigger since the repeated value error comes first
 E0136: r##"
 A binary can only have one entry point, and by default that entry point is the
@@ -1139,11 +1105,13 @@ already specify all requirements that will be used for every type parameter.
 "##,
 
 E0281: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
 You tried to supply a type which doesn't implement some trait in a location
 which expected that trait. This error typically occurs when working with
 `Fn`-based types. Erroneous code example:
 
-```compile_fail,E0281
+```compile-fail
 fn foo<F: Fn(usize)>(x: F) { }
 
 fn main() {
@@ -1383,74 +1351,6 @@ struct Foo<T: 'static> {
 ```
 "##,
 
-E0312: r##"
-A lifetime of reference outlives lifetime of borrowed content.
-
-Erroneous code example:
-
-```compile_fail,E0312
-fn make_child<'tree, 'human>(
-  x: &'human i32,
-  y: &'tree i32
-) -> &'human i32 {
-    if x > y
-       { x }
-    else
-       { y }
-       // error: lifetime of reference outlives lifetime of borrowed content
-}
-```
-
-The function declares that it returns a reference with the `'human`
-lifetime, but it may return data with the `'tree` lifetime. As neither
-lifetime is declared longer than the other, this results in an
-error. Sometimes, this error is because the function *body* is
-incorrect -- that is, maybe you did not *mean* to return data from
-`y`. In that case, you should fix the function body.
-
-Often, however, the body is correct. In that case, the function
-signature needs to be altered to match the body, so that the caller
-understands that data from either `x` or `y` may be returned. The
-simplest way to do this is to give both function parameters the *same*
-named lifetime:
-
-```
-fn make_child<'human>(
-  x: &'human i32,
-  y: &'human i32
-) -> &'human i32 {
-    if x > y
-       { x }
-    else
-       { y } // ok!
-}
-```
-
-However, in some cases, you may prefer to explicitly declare that one lifetime
-outlives another using a `where` clause:
-
-```
-fn make_child<'tree, 'human>(
-  x: &'human i32,
-  y: &'tree i32
-) -> &'human i32
-where
-  'tree: 'human
-{
-    if x > y
-       { x }
-    else
-       { y } // ok!
-}
-```
-
-Here, the where clause `'tree: 'human` can be read as "the lifetime
-'tree outlives the lifetime 'human" -- meaning, references with the
-`'tree` lifetime live *at least as long as* references with the
-`'human` lifetime. Therefore, it is safe to return data with lifetime
-`'tree` when data with the lifetime `'human` is needed.
-"##,
-
 E0317: r##"
 This error occurs when an `if` expression without an `else` block is used in a
 context where a type other than `()` is expected, for example a `let`
@@ -2060,6 +1960,7 @@ register_diagnostics! {
 //  E0304, // expected signed integer constant
 //  E0305, // expected constant
     E0311, // thing may not live long enough
+    E0312, // lifetime of reference outlives lifetime of borrowed content
     E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
@@ -2086,4 +1987,6 @@ register_diagnostics! {
     E0566, // conflicting representation hints
     E0623, // lifetime mismatch where both parameters are anonymous regions
     E0628, // generators cannot have explicit arguments
+    E0631, // type mismatch in closure arguments
+    E0637, // "'_" is not a valid lifetime bound
 }
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 78daff9f67a..8e48352007b 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -97,6 +97,17 @@ impl serialize::UseSpecializedDecodable for CrateNum {
            RustcDecodable, Hash, Copy)]
 pub struct DefIndex(u32);
 
+impl Idx for DefIndex {
+    fn new(value: usize) -> Self {
+        assert!(value < (u32::MAX) as usize);
+        DefIndex(value as u32)
+    }
+
+    fn index(self) -> usize {
+        self.0 as usize
+    }
+}
+
 impl fmt::Debug for DefIndex {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 9d8075de2eb..1755b3bca05 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -422,7 +422,12 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
 
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
     visitor.visit_id(lifetime.id);
-    visitor.visit_name(lifetime.span, lifetime.name);
+    match lifetime.name {
+        LifetimeName::Name(name) => {
+            visitor.visit_name(lifetime.span, name);
+        }
+        LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {}
+    }
 }
 
 pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
@@ -622,7 +627,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
     visitor.visit_name(path_span, segment.name);
-    visitor.visit_path_parameters(path_span, &segment.parameters);
+    if let Some(ref parameters) = segment.parameters {
+        visitor.visit_path_parameters(path_span, parameters);
+    }
 }
 
 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index c7ea9c47028..1fdfbe20328 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -65,7 +65,7 @@ use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind};
 use syntax::std_inject;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::{TokenStream, TokenTree, Delimited};
-use syntax::parse::token::{Token, DelimToken};
+use syntax::parse::token::Token;
 use syntax::util::small_vector::SmallVector;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
@@ -606,10 +606,12 @@ impl<'a> LoweringContext<'a> {
     }
 
     fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
-        tokens.into_trees().map(|tree| self.lower_token_tree(tree)).collect()
+        tokens.into_trees()
+            .flat_map(|tree| self.lower_token_tree(tree).into_trees())
+            .collect()
     }
 
-    fn lower_token_tree(&mut self, tree: TokenTree) -> TokenTree {
+    fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream {
         match tree {
             TokenTree::Token(span, token) => {
                 self.lower_token(token, span)
@@ -618,23 +620,19 @@ impl<'a> LoweringContext<'a> {
                 TokenTree::Delimited(span, Delimited {
                     delim: delimited.delim,
                     tts: self.lower_token_stream(delimited.tts.into()).into(),
-                })
+                }).into()
             }
         }
     }
 
-    fn lower_token(&mut self, token: Token, span: Span) -> TokenTree {
+    fn lower_token(&mut self, token: Token, span: Span) -> TokenStream {
         match token {
             Token::Interpolated(_) => {}
-            other => return TokenTree::Token(span, other),
+            other => return TokenTree::Token(span, other).into(),
         }
 
         let tts = token.interpolated_to_tokenstream(&self.sess.parse_sess, span);
-        let tts = self.lower_token_stream(tts);
-        TokenTree::Delimited(span, Delimited {
-            delim: DelimToken::NoDelim,
-            tts: tts.into(),
-        })
+        self.lower_token_stream(tts)
     }
 
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
@@ -685,17 +683,16 @@ impl<'a> LoweringContext<'a> {
                 return self.lower_ty(ty);
             }
             TyKind::Path(ref qself, ref path) => {
-                let id = self.lower_node_id(t.id).node_id;
+                let id = self.lower_node_id(t.id);
                 let qpath = self.lower_qpath(t.id, qself, path, ParamMode::Explicit);
                 return self.ty_path(id, t.span, qpath);
             }
             TyKind::ImplicitSelf => {
                 hir::TyPath(hir::QPath::Resolved(None, P(hir::Path {
                     def: self.expect_full_def(t.id),
-                    segments: hir_vec![hir::PathSegment {
-                        name: keywords::SelfType.name(),
-                        parameters: hir::PathParameters::none()
-                    }],
+                    segments: hir_vec![
+                        hir::PathSegment::from_name(keywords::SelfType.name())
+                    ],
                     span: t.span,
                 })))
             }
@@ -734,10 +731,12 @@ impl<'a> LoweringContext<'a> {
             TyKind::Mac(_) => panic!("TyMac should have been expanded by now."),
         };
 
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(t.id);
         P(hir::Ty {
-            id: self.lower_node_id(t.id).node_id,
+            id: node_id,
             node: kind,
             span: t.span,
+            hir_id,
         })
     }
 
@@ -863,7 +862,7 @@ impl<'a> LoweringContext<'a> {
             // Otherwise, the base path is an implicit `Self` type path,
             // e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
             // `<I as Iterator>::Item::default`.
-            let new_id = self.next_id().node_id;
+            let new_id = self.next_id();
             self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))
         };
 
@@ -888,7 +887,7 @@ impl<'a> LoweringContext<'a> {
             }
 
             // Wrap the associated extension in another type node.
-            let new_id = self.next_id().node_id;
+            let new_id = self.next_id();
             ty = self.ty_path(new_id, p.span, qpath);
         }
 
@@ -914,12 +913,8 @@ impl<'a> LoweringContext<'a> {
             segments: segments.map(|segment| {
                 self.lower_path_segment(p.span, segment, param_mode, 0,
                                         ParenthesizedGenericArgs::Err)
-            }).chain(name.map(|name| {
-                hir::PathSegment {
-                    name,
-                    parameters: hir::PathParameters::none()
-                }
-            })).collect(),
+            }).chain(name.map(|name| hir::PathSegment::from_name(name)))
+              .collect(),
             span: p.span,
         }
     }
@@ -940,7 +935,7 @@ impl<'a> LoweringContext<'a> {
                           expected_lifetimes: usize,
                           parenthesized_generic_args: ParenthesizedGenericArgs)
                           -> hir::PathSegment {
-        let mut parameters = if let Some(ref parameters) = segment.parameters {
+        let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters {
             let msg = "parenthesized parameters may only be used with a trait";
             match **parameters {
                 PathParameters::AngleBracketed(ref data) => {
@@ -951,12 +946,12 @@ impl<'a> LoweringContext<'a> {
                     ParenthesizedGenericArgs::Warn => {
                         self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
                                               CRATE_NODE_ID, data.span, msg.into());
-                        hir::PathParameters::none()
+                        (hir::PathParameters::none(), true)
                     }
                     ParenthesizedGenericArgs::Err => {
                         struct_span_err!(self.sess, data.span, E0214, "{}", msg)
                             .span_label(data.span, "only traits may use parentheses").emit();
-                        hir::PathParameters::none()
+                        (hir::PathParameters::none(), true)
                     }
                 }
             }
@@ -970,39 +965,39 @@ impl<'a> LoweringContext<'a> {
             }).collect();
         }
 
-        hir::PathSegment {
-            name: self.lower_ident(segment.identifier),
+        hir::PathSegment::new(
+            self.lower_ident(segment.identifier),
             parameters,
-        }
+            infer_types
+        )
     }
 
     fn lower_angle_bracketed_parameter_data(&mut self,
                                             data: &AngleBracketedParameterData,
                                             param_mode: ParamMode)
-                                            -> hir::PathParameters {
+                                            -> (hir::PathParameters, bool) {
         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
-        hir::PathParameters {
+        (hir::PathParameters {
             lifetimes: self.lower_lifetimes(lifetimes),
             types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
-            infer_types: types.is_empty() && param_mode == ParamMode::Optional,
             bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
             parenthesized: false,
-        }
+        }, types.is_empty() && param_mode == ParamMode::Optional)
     }
 
     fn lower_parenthesized_parameter_data(&mut self,
                                           data: &ParenthesizedParameterData)
-                                          -> hir::PathParameters {
+                                          -> (hir::PathParameters, bool) {
         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
         let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
         let mk_tup = |this: &mut Self, tys, span| {
-            P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span })
+            let LoweredNodeId { node_id, hir_id } = this.next_id();
+            P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
         };
 
-        hir::PathParameters {
+        (hir::PathParameters {
             lifetimes: hir::HirVec::new(),
             types: hir_vec![mk_tup(self, inputs, span)],
-            infer_types: false,
             bindings: hir_vec![hir::TypeBinding {
                 id: self.next_id().node_id,
                 name: Symbol::intern(FN_OUTPUT_NAME),
@@ -1011,7 +1006,7 @@ impl<'a> LoweringContext<'a> {
                 span: output.as_ref().map_or(span, |ty| ty.span),
             }],
             parenthesized: true,
-        }
+        }, false)
     }
 
     fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
@@ -1108,6 +1103,10 @@ impl<'a> LoweringContext<'a> {
             default: tp.default.as_ref().map(|x| self.lower_ty(x)),
             span: tp.span,
             pure_wrt_drop: tp.attrs.iter().any(|attr| attr.check_name("may_dangle")),
+            synthetic: tp.attrs.iter()
+                               .filter(|attr| attr.check_name("rustc_synthetic"))
+                               .map(|_| hir::SyntheticTyParamKind::ImplTrait)
+                               .nth(0),
         }
     }
 
@@ -1121,7 +1120,11 @@ impl<'a> LoweringContext<'a> {
     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
         hir::Lifetime {
             id: self.lower_node_id(l.id).node_id,
-            name: self.lower_ident(l.ident),
+            name: match self.lower_ident(l.ident) {
+                x if x == "'_" => hir::LifetimeName::Underscore,
+                x if x == "'static" => hir::LifetimeName::Static,
+                name => hir::LifetimeName::Name(name),
+            },
             span: l.span,
         }
     }
@@ -1865,7 +1868,7 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
         match *e {
-            RangeEnd::Included => hir::RangeEnd::Included,
+            RangeEnd::Included(_) => hir::RangeEnd::Included,
             RangeEnd::Excluded => hir::RangeEnd::Excluded,
         }
     }
@@ -2972,7 +2975,7 @@ impl<'a> LoweringContext<'a> {
         self.expr_block(block, attrs)
     }
 
-    fn ty_path(&mut self, id: NodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
+    fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
         let mut id = id;
         let node = match qpath {
             hir::QPath::Resolved(None, path) => {
@@ -2982,14 +2985,14 @@ impl<'a> LoweringContext<'a> {
                         bound_lifetimes: hir_vec![],
                         trait_ref: hir::TraitRef {
                             path: path.and_then(|path| path),
-                            ref_id: id,
+                            ref_id: id.node_id,
                         },
                         span,
                     };
 
                     // The original ID is taken by the `PolyTraitRef`,
                     // so the `Ty` itself needs a different one.
-                    id = self.next_id().node_id;
+                    id = self.next_id();
 
                     hir::TyTraitObject(hir_vec![principal], self.elided_lifetime(span))
                 } else {
@@ -2998,14 +3001,14 @@ impl<'a> LoweringContext<'a> {
             }
             _ => hir::TyPath(qpath)
         };
-        P(hir::Ty { id, node, span })
+        P(hir::Ty { id: id.node_id, hir_id: id.hir_id, node, span })
     }
 
     fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
         hir::Lifetime {
             id: self.next_id().node_id,
             span,
-            name: keywords::Invalid.name()
+            name: hir::LifetimeName::Implicit,
         }
     }
 }
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index a54068c6483..80fadcda277 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -16,6 +16,9 @@ use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax_pos::Span;
 
+use ich::StableHashingContext;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+
 /// A Visitor that walks over the HIR and collects Nodes into a HIR map
 pub(super) struct NodeCollector<'a, 'hir> {
     /// The crate
@@ -25,37 +28,113 @@ pub(super) struct NodeCollector<'a, 'hir> {
     /// The parent of this node
     parent_node: NodeId,
 
+    // These fields keep track of the currently relevant DepNodes during
+    // the visitor's traversal.
     current_dep_node_owner: DefIndex,
-    current_dep_node_index: DepNodeIndex,
+    current_signature_dep_index: DepNodeIndex,
+    current_full_dep_index: DepNodeIndex,
+    currently_in_body: bool,
 
     dep_graph: &'a DepGraph,
     definitions: &'a definitions::Definitions,
+
+    hcx: StableHashingContext<'a>,
+
+    // We are collecting DepNode::HirBody hashes here so we can compute the
+    // crate hash from then later on.
+    hir_body_nodes: Vec<DefPathHash>,
 }
 
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(krate: &'hir Crate,
-                dep_graph: &'a DepGraph,
-                definitions: &'a definitions::Definitions)
+                       dep_graph: &'a DepGraph,
+                       definitions: &'a definitions::Definitions,
+                       hcx: StableHashingContext<'a>)
                 -> NodeCollector<'a, 'hir> {
         let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
-        let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir);
-        let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node);
+
+        // Allocate DepNodes for the root module
+        let (root_mod_sig_dep_index, root_mod_full_dep_index);
+        {
+            let Crate {
+                ref module,
+                // Crate attributes are not copied over to the root `Mod`, so hash
+                // them explicitly here.
+                ref attrs,
+                span,
+
+                // These fields are handled separately:
+                exported_macros: _,
+                items: _,
+                trait_items: _,
+                impl_items: _,
+                bodies: _,
+                trait_impls: _,
+                trait_default_impl: _,
+                body_ids: _,
+            } = *krate;
+
+            root_mod_sig_dep_index = dep_graph.with_task(
+                root_mod_def_path_hash.to_dep_node(DepKind::Hir),
+                &hcx,
+                HirItemLike { item_like: (module, attrs, span), hash_bodies: false },
+                identity_fn
+            ).1;
+            root_mod_full_dep_index = dep_graph.with_task(
+                root_mod_def_path_hash.to_dep_node(DepKind::HirBody),
+                &hcx,
+                HirItemLike { item_like: (module, attrs, span), hash_bodies: true },
+                identity_fn
+            ).1;
+        }
+
+        {
+            dep_graph.with_task(
+                DepNode::new_no_params(DepKind::AllLocalTraitImpls),
+                &hcx,
+                &krate.trait_impls,
+                identity_fn
+            );
+        }
+
+        let hir_body_nodes = vec![root_mod_def_path_hash];
 
         let mut collector = NodeCollector {
             krate,
             map: vec![],
             parent_node: CRATE_NODE_ID,
-            current_dep_node_index: root_mod_dep_node_index,
+            current_signature_dep_index: root_mod_sig_dep_index,
+            current_full_dep_index: root_mod_full_dep_index,
             current_dep_node_owner: CRATE_DEF_INDEX,
+            currently_in_body: false,
             dep_graph,
             definitions,
+            hcx,
+            hir_body_nodes,
         };
-        collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index));
+        collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_sig_dep_index));
 
         collector
     }
 
-    pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> {
+    pub(super) fn finalize_and_compute_crate_hash(self,
+                                                  crate_disambiguator: &str)
+                                                  -> Vec<MapEntry<'hir>> {
+        let mut node_hashes: Vec<_> = self
+            .hir_body_nodes
+            .iter()
+            .map(|&def_path_hash| {
+                let dep_node = def_path_hash.to_dep_node(DepKind::HirBody);
+                (def_path_hash, self.dep_graph.fingerprint_of(&dep_node))
+            })
+            .collect();
+
+        node_hashes.sort_unstable_by(|&(ref d1, _), &(ref d2, _)| d1.cmp(d2));
+
+        self.dep_graph.with_task(DepNode::new_no_params(DepKind::Krate),
+                                 &self.hcx,
+                                 (node_hashes, crate_disambiguator),
+                                 identity_fn);
         self.map
     }
 
@@ -70,7 +149,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
 
     fn insert(&mut self, id: NodeId, node: Node<'hir>) {
         let parent = self.parent_node;
-        let dep_node_index = self.current_dep_node_index;
+        let dep_node_index = if self.currently_in_body {
+            self.current_full_dep_index
+        } else {
+            self.current_signature_dep_index
+        };
 
         let entry = match node {
             NodeItem(n) => EntryItem(parent, dep_node_index, n),
@@ -91,6 +174,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
             NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
             NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
+            NodeMacroDef(n) => EntryMacroDef(dep_node_index, n),
         };
 
         // Make sure that the DepNode of some node coincides with the HirId
@@ -127,22 +211,41 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
         self.parent_node = parent_node;
     }
 
-    fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self,
+    fn with_dep_node_owner<T: HashStable<StableHashingContext<'a>>,
+                           F: FnOnce(&mut Self)>(&mut self,
                                                  dep_node_owner: DefIndex,
+                                                 item_like: &T,
                                                  f: F) {
         let prev_owner = self.current_dep_node_owner;
-        let prev_index = self.current_dep_node_index;
-
-        // When we enter a new owner (item, impl item, or trait item), we always
-        // start out again with DepKind::Hir.
-        let new_dep_node = self.definitions
-                               .def_path_hash(dep_node_owner)
-                               .to_dep_node(DepKind::Hir);
-        self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
+        let prev_signature_dep_index = self.current_signature_dep_index;
+        let prev_full_dep_index = self.current_signature_dep_index;
+        let prev_in_body = self.currently_in_body;
+
+        let def_path_hash = self.definitions.def_path_hash(dep_node_owner);
+
+        self.current_signature_dep_index = self.dep_graph.with_task(
+            def_path_hash.to_dep_node(DepKind::Hir),
+            &self.hcx,
+            HirItemLike { item_like, hash_bodies: false },
+            identity_fn
+        ).1;
+
+        self.current_full_dep_index = self.dep_graph.with_task(
+            def_path_hash.to_dep_node(DepKind::HirBody),
+            &self.hcx,
+            HirItemLike { item_like, hash_bodies: true },
+            identity_fn
+        ).1;
+
+        self.hir_body_nodes.push(def_path_hash);
+
         self.current_dep_node_owner = dep_node_owner;
+        self.currently_in_body = false;
         f(self);
-        self.current_dep_node_index = prev_index;
+        self.currently_in_body = prev_in_body;
         self.current_dep_node_owner = prev_owner;
+        self.current_full_dep_index = prev_full_dep_index;
+        self.current_signature_dep_index = prev_signature_dep_index;
     }
 }
 
@@ -169,24 +272,17 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_nested_body(&mut self, id: BodyId) {
-        // When we enter a body, we switch to DepKind::HirBody.
-        // Note that current_dep_node_index might already be DepKind::HirBody,
-        // e.g. when entering the body of a closure that is already part of a
-        // surrounding body. That's expected and not a problem.
-        let prev_index = self.current_dep_node_index;
-        let new_dep_node = self.definitions
-                               .def_path_hash(self.current_dep_node_owner)
-                               .to_dep_node(DepKind::HirBody);
-        self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
+        let prev_in_body = self.currently_in_body;
+        self.currently_in_body = true;
         self.visit_body(self.krate.body(id));
-        self.current_dep_node_index = prev_index;
+        self.currently_in_body = prev_in_body;
     }
 
     fn visit_item(&mut self, i: &'hir Item) {
         debug!("visit_item: {:?}", i);
         debug_assert_eq!(i.hir_id.owner,
                          self.definitions.opt_def_index(i.id).unwrap());
-        self.with_dep_node_owner(i.hir_id.owner, |this| {
+        self.with_dep_node_owner(i.hir_id.owner, i, |this| {
             this.insert(i.id, NodeItem(i));
             this.with_parent(i.id, |this| {
                 match i.node {
@@ -222,7 +318,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
         debug_assert_eq!(ti.hir_id.owner,
                          self.definitions.opt_def_index(ti.id).unwrap());
-        self.with_dep_node_owner(ti.hir_id.owner, |this| {
+        self.with_dep_node_owner(ti.hir_id.owner, ti, |this| {
             this.insert(ti.id, NodeTraitItem(ti));
 
             this.with_parent(ti.id, |this| {
@@ -234,7 +330,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
         debug_assert_eq!(ii.hir_id.owner,
                          self.definitions.opt_def_index(ii.id).unwrap());
-        self.with_dep_node_owner(ii.hir_id.owner, |this| {
+        self.with_dep_node_owner(ii.hir_id.owner, ii, |this| {
             this.insert(ii.id, NodeImplItem(ii));
 
             this.with_parent(ii.id, |this| {
@@ -328,7 +424,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) {
-        self.insert_entry(macro_def.id, NotPresent);
+        let def_index = self.definitions.opt_def_index(macro_def.id).unwrap();
+
+        self.with_dep_node_owner(def_index, macro_def, |this| {
+            this.insert(macro_def.id, NodeMacroDef(macro_def));
+        });
     }
 
     fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: NodeId) {
@@ -375,3 +475,28 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         self.visit_nested_impl_item(id);
     }
 }
+
+// We use this with DepGraph::with_task(). Since we are handling only input
+// values here, the "task" computing them just passes them through.
+fn identity_fn<T>(_: &StableHashingContext, item_like: T) -> T {
+    item_like
+}
+
+// This is a wrapper structure that allows determining if span values within
+// the wrapped item should be hashed or not.
+struct HirItemLike<T> {
+    item_like: T,
+    hash_bodies: bool,
+}
+
+impl<'hir, T> HashStable<StableHashingContext<'hir>> for HirItemLike<T>
+    where T: HashStable<StableHashingContext<'hir>>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'hir>,
+                                          hasher: &mut StableHasher<W>) {
+        hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| {
+            self.item_like.hash_stable(hcx, hasher);
+        });
+    }
+}
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index b2d6886e7f2..8ce2feab06c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -57,6 +57,7 @@ pub enum Node<'hir> {
     NodePat(&'hir Pat),
     NodeBlock(&'hir Block),
     NodeLocal(&'hir Local),
+    NodeMacroDef(&'hir MacroDef),
 
     /// NodeStructCtor represents a tuple struct.
     NodeStructCtor(&'hir VariantData),
@@ -93,6 +94,8 @@ enum MapEntry<'hir> {
     EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
     EntryLocal(NodeId, DepNodeIndex, &'hir Local),
 
+    EntryMacroDef(DepNodeIndex, &'hir MacroDef),
+
     /// Roots for node trees. The DepNodeIndex is the dependency node of the
     /// crate's root module.
     RootCrate(DepNodeIndex),
@@ -127,6 +130,7 @@ impl<'hir> MapEntry<'hir> {
             EntryLocal(id, _, _) => id,
 
             NotPresent |
+            EntryMacroDef(..) |
             RootCrate(_) => return None,
         })
     }
@@ -151,6 +155,7 @@ impl<'hir> MapEntry<'hir> {
             EntryTyParam(_, _, n) => NodeTyParam(n),
             EntryVisibility(_, _, n) => NodeVisibility(n),
             EntryLocal(_, _, n) => NodeLocal(n),
+            EntryMacroDef(_, n) => NodeMacroDef(n),
 
             NotPresent |
             RootCrate(_) => return None
@@ -285,20 +290,12 @@ impl<'hir> Map<'hir> {
             EntryVisibility(_, dep_node_index, _) |
             EntryExpr(_, dep_node_index, _) |
             EntryLocal(_, dep_node_index, _) |
+            EntryMacroDef(dep_node_index, _) |
             RootCrate(dep_node_index) => {
                 self.dep_graph.read_index(dep_node_index);
             }
             NotPresent => {
-                // Some nodes, notably macro definitions, are not
-                // present in the map for whatever reason, but
-                // they *do* have def-ids. So if we encounter an
-                // empty hole, check for that case.
-                if let Some(def_index) = self.definitions.opt_def_index(id) {
-                    let def_path_hash = self.definitions.def_path_hash(def_index);
-                    self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
-                } else {
-                    bug!("called HirMap::read() with invalid NodeId")
-                }
+                bug!("called HirMap::read() with invalid NodeId")
             }
         }
     }
@@ -805,7 +802,7 @@ impl<'hir> Map<'hir> {
             NodeTraitItem(ti) => ti.name,
             NodeVariant(v) => v.node.name,
             NodeField(f) => f.name,
-            NodeLifetime(lt) => lt.name,
+            NodeLifetime(lt) => lt.name.name(),
             NodeTyParam(tp) => tp.name,
             NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
             NodeStructCtor(_) => self.name(self.get_parent(id)),
@@ -875,20 +872,11 @@ impl<'hir> Map<'hir> {
             Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
             Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
             Some(EntryLocal(_, _, local)) => local.span,
+            Some(EntryMacroDef(_, macro_def)) => macro_def.span,
 
             Some(RootCrate(_)) => self.forest.krate.span,
             Some(NotPresent) | None => {
-                // Some nodes, notably macro definitions, are not
-                // present in the map for whatever reason, but
-                // they *do* have def-ids. So if we encounter an
-                // empty hole, check for that case.
-                if let Some(def_index) = self.definitions.opt_def_index(id) {
-                    let def_path_hash = self.definitions.def_path_hash(def_index);
-                    self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
-                    DUMMY_SP
-                } else {
-                    bug!("hir::map::Map::span: id not in map: {:?}", id)
-                }
+                bug!("hir::map::Map::span: id not in map: {:?}", id)
             }
         }
     }
@@ -1012,15 +1000,22 @@ impl Named for StructField { fn name(&self) -> Name { self.name } }
 impl Named for TraitItem { fn name(&self) -> Name { self.name } }
 impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 
-pub fn map_crate<'hir>(forest: &'hir mut Forest,
+pub fn map_crate<'hir>(sess: &::session::Session,
+                       cstore: &::middle::cstore::CrateStore,
+                       forest: &'hir mut Forest,
                        definitions: &'hir Definitions)
                        -> Map<'hir> {
     let map = {
+        let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
+
         let mut collector = NodeCollector::root(&forest.krate,
                                                 &forest.dep_graph,
-                                                &definitions);
+                                                &definitions,
+                                                hcx);
         intravisit::walk_crate(&mut collector, &forest.krate);
-        collector.into_map()
+
+        let crate_disambiguator = sess.local_crate_disambiguator().as_str();
+        collector.finalize_and_compute_crate_hash(&crate_disambiguator)
     };
 
     if log_enabled!(::log::LogLevel::Debug) {
@@ -1103,6 +1098,7 @@ impl<'a> print::State<'a> {
             // printing.
             NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
             NodeLocal(a)       => self.print_local_decl(&a),
+            NodeMacroDef(_)    => bug!("cannot print MacroDef"),
         }
     }
 }
@@ -1219,6 +1215,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeVisibility(ref vis)) => {
             format!("visibility {:?}{}", vis, id_str)
         }
+        Some(NodeMacroDef(_)) => {
+            format!("macro {}{}",  path_str(), id_str)
+        }
         None => {
             format!("unknown node{}", id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index c250695f361..9bfedd7a381 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -145,7 +145,27 @@ pub struct Lifetime {
     /// HIR lowering inserts these placeholders in type paths that
     /// refer to type definitions needing lifetime parameters,
     /// `&T` and `&mut T`, and trait objects without `... + 'a`.
-    pub name: Name,
+    pub name: LifetimeName,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+pub enum LifetimeName {
+    Implicit,
+    Underscore,
+    Static,
+    Name(Name),
+}
+
+impl LifetimeName {
+    pub fn name(&self) -> Name {
+        use self::LifetimeName::*;
+        match *self {
+            Implicit => keywords::Invalid.name(),
+            Underscore => Symbol::intern("'_"),
+            Static => keywords::StaticLifetime.name(),
+            Name(name) => name,
+        }
+    }
 }
 
 impl fmt::Debug for Lifetime {
@@ -159,11 +179,15 @@ impl fmt::Debug for Lifetime {
 
 impl Lifetime {
     pub fn is_elided(&self) -> bool {
-        self.name == keywords::Invalid.name()
+        use self::LifetimeName::*;
+        match self.name {
+            Implicit | Underscore => true,
+            Static | Name(_) => false,
+        }
     }
 
     pub fn is_static(&self) -> bool {
-        self.name == "'static"
+        self.name == LifetimeName::Static
     }
 }
 
@@ -212,7 +236,13 @@ pub struct PathSegment {
     /// this is more than just simple syntactic sugar; the use of
     /// parens affects the region binding rules, so we preserve the
     /// distinction.
-    pub parameters: PathParameters,
+    pub parameters: Option<P<PathParameters>>,
+
+    /// Whether to infer remaining type parameters, if any.
+    /// This only applies to expression and pattern paths, and
+    /// out of those only the segments with no type parameters
+    /// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
+    pub infer_types: bool,
 }
 
 impl PathSegment {
@@ -220,9 +250,35 @@ impl PathSegment {
     pub fn from_name(name: Name) -> PathSegment {
         PathSegment {
             name,
-            parameters: PathParameters::none()
+            infer_types: true,
+            parameters: None
+        }
+    }
+
+    pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self {
+        PathSegment {
+            name,
+            infer_types,
+            parameters: if parameters.is_empty() {
+                None
+            } else {
+                Some(P(parameters))
+            }
         }
     }
+
+    // FIXME: hack required because you can't create a static
+    // PathParameters, so you can't just return a &PathParameters.
+    pub fn with_parameters<F, R>(&self, f: F) -> R
+        where F: FnOnce(&PathParameters) -> R
+    {
+        let dummy = PathParameters::none();
+        f(if let Some(ref params) = self.parameters {
+            &params
+        } else {
+            &dummy
+        })
+    }
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -231,11 +287,6 @@ pub struct PathParameters {
     pub lifetimes: HirVec<Lifetime>,
     /// The type parameters for this path segment, if present.
     pub types: HirVec<P<Ty>>,
-    /// Whether to infer remaining type parameters, if any.
-    /// This only applies to expression and pattern paths, and
-    /// out of those only the segments with no type parameters
-    /// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
-    pub infer_types: bool,
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
@@ -250,12 +301,16 @@ impl PathParameters {
         Self {
             lifetimes: HirVec::new(),
             types: HirVec::new(),
-            infer_types: true,
             bindings: HirVec::new(),
             parenthesized: false,
         }
     }
 
+    pub fn is_empty(&self) -> bool {
+        self.lifetimes.is_empty() && self.types.is_empty() &&
+            self.bindings.is_empty() && !self.parenthesized
+    }
+
     pub fn inputs(&self) -> &[P<Ty>] {
         if self.parenthesized {
             if let Some(ref ty) = self.types.get(0) {
@@ -296,6 +351,7 @@ pub struct TyParam {
     pub default: Option<P<Ty>>,
     pub span: Span,
     pub pure_wrt_drop: bool,
+    pub synthetic: Option<SyntheticTyParamKind>,
 }
 
 /// Represents lifetimes and type parameters attached to a declaration
@@ -364,6 +420,13 @@ impl Generics {
     }
 }
 
+/// Synthetic Type Parameters are converted to an other form during lowering, this allows
+/// to track the original form they had. Usefull for error messages.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum SyntheticTyParamKind {
+    ImplTrait
+}
+
 /// A `where` clause in a definition
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct WhereClause {
@@ -1330,6 +1393,7 @@ pub struct Ty {
     pub id: NodeId,
     pub node: Ty_,
     pub span: Span,
+    pub hir_id: HirId,
 }
 
 impl fmt::Debug for Ty {
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 41a253f7904..5daffe667fd 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1213,11 +1213,17 @@ impl<'a> State<'a> {
         self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
         self.s.word(".")?;
         self.print_name(segment.name)?;
-        if !segment.parameters.lifetimes.is_empty() ||
-                !segment.parameters.types.is_empty() ||
-                !segment.parameters.bindings.is_empty() {
-            self.print_path_parameters(&segment.parameters, true)?;
-        }
+
+        segment.with_parameters(|parameters| {
+            if !parameters.lifetimes.is_empty() ||
+                !parameters.types.is_empty() ||
+                !parameters.bindings.is_empty()
+            {
+                self.print_path_parameters(&parameters, segment.infer_types, true)
+            } else {
+                Ok(())
+            }
+        })?;
         self.print_call_post(base_args)
     }
 
@@ -1564,8 +1570,12 @@ impl<'a> State<'a> {
             }
             if segment.name != keywords::CrateRoot.name() &&
                segment.name != keywords::DollarCrate.name() {
-                self.print_name(segment.name)?;
-                self.print_path_parameters(&segment.parameters, colons_before_params)?;
+               self.print_name(segment.name)?;
+               segment.with_parameters(|parameters| {
+                   self.print_path_parameters(parameters,
+                                              segment.infer_types,
+                                              colons_before_params)
+               })?;
             }
         }
 
@@ -1593,7 +1603,11 @@ impl<'a> State<'a> {
                     if segment.name != keywords::CrateRoot.name() &&
                        segment.name != keywords::DollarCrate.name() {
                         self.print_name(segment.name)?;
-                        self.print_path_parameters(&segment.parameters, colons_before_params)?;
+                        segment.with_parameters(|parameters| {
+                            self.print_path_parameters(parameters,
+                                                       segment.infer_types,
+                                                       colons_before_params)
+                        })?;
                     }
                 }
 
@@ -1601,7 +1615,11 @@ impl<'a> State<'a> {
                 self.s.word("::")?;
                 let item_segment = path.segments.last().unwrap();
                 self.print_name(item_segment.name)?;
-                self.print_path_parameters(&item_segment.parameters, colons_before_params)
+                item_segment.with_parameters(|parameters| {
+                    self.print_path_parameters(parameters,
+                                               item_segment.infer_types,
+                                               colons_before_params)
+                })
             }
             hir::QPath::TypeRelative(ref qself, ref item_segment) => {
                 self.s.word("<")?;
@@ -1609,13 +1627,18 @@ impl<'a> State<'a> {
                 self.s.word(">")?;
                 self.s.word("::")?;
                 self.print_name(item_segment.name)?;
-                self.print_path_parameters(&item_segment.parameters, colons_before_params)
+                item_segment.with_parameters(|parameters| {
+                    self.print_path_parameters(parameters,
+                                               item_segment.infer_types,
+                                               colons_before_params)
+                })
             }
         }
     }
 
     fn print_path_parameters(&mut self,
                              parameters: &hir::PathParameters,
+                             infer_types: bool,
                              colons_before_params: bool)
                              -> io::Result<()> {
         if parameters.parenthesized {
@@ -1652,7 +1675,7 @@ impl<'a> State<'a> {
 
             // FIXME(eddyb) This would leak into error messages, e.g.:
             // "non-exhaustive patterns: `Some::<..>(_)` not covered".
-            if parameters.infer_types && false {
+            if infer_types && false {
                 start_or_comma(self)?;
                 self.s.word("..")?;
             }
@@ -1975,7 +1998,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
-        self.print_name(lifetime.name)
+        self.print_name(lifetime.name.name())
     }
 
     pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs
index 71e442b3bb2..e3934590278 100644
--- a/src/librustc/ich/caching_codemap_view.rs
+++ b/src/librustc/ich/caching_codemap_view.rs
@@ -22,6 +22,7 @@ struct CacheEntry {
     file_index: usize,
 }
 
+#[derive(Clone)]
 pub struct CachingCodemapView<'cm> {
     codemap: &'cm CodeMap,
     line_cache: [CacheEntry; 3],
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index 64fc63002da..e7a26e14db5 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -43,6 +43,7 @@ thread_local!(static IGNORED_ATTR_NAMES: RefCell<FxHashSet<Symbol>> =
 /// enough information to transform DefIds and HirIds into stable DefPaths (i.e.
 /// a reference to the TyCtxt) and it holds a few caches for speeding up various
 /// things (e.g. each DefId/DefPath is only hashed once).
+#[derive(Clone)]
 pub struct StableHashingContext<'gcx> {
     sess: &'gcx Session,
     definitions: &'gcx Definitions,
@@ -169,6 +170,11 @@ impl<'gcx> StableHashingContext<'gcx> {
     }
 
     #[inline]
+    pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
+        self.definitions.node_to_hir_id(node_id)
+    }
+
+    #[inline]
     pub fn hash_spans(&self) -> bool {
         self.hash_spans
     }
@@ -259,6 +265,18 @@ impl<'a, 'gcx, 'lcx> StableHashingContextProvider for TyCtxt<'a, 'gcx, 'lcx> {
     }
 }
 
+
+impl<'gcx> StableHashingContextProvider for StableHashingContext<'gcx> {
+    type ContextType = StableHashingContext<'gcx>;
+    fn create_stable_hashing_context(&self) -> Self::ContextType {
+        self.clone()
+    }
+}
+
+impl<'gcx> ::dep_graph::DepGraphSafe for StableHashingContext<'gcx> {
+}
+
+
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::BodyId {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 9582b03ce1c..776f85cf5da 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -123,6 +123,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId {
     }
 }
 
+impl_stable_hash_for!(enum hir::LifetimeName {
+    Implicit,
+    Underscore,
+    Static,
+    Name(name)
+});
+
 impl_stable_hash_for!(struct hir::Lifetime {
     id,
     span,
@@ -143,13 +150,13 @@ impl_stable_hash_for!(struct hir::Path {
 
 impl_stable_hash_for!(struct hir::PathSegment {
     name,
+    infer_types,
     parameters
 });
 
 impl_stable_hash_for!(struct hir::PathParameters {
     lifetimes,
     types,
-    infer_types,
     bindings,
     parenthesized
 });
@@ -170,7 +177,8 @@ impl_stable_hash_for!(struct hir::TyParam {
     bounds,
     default,
     span,
-    pure_wrt_drop
+    pure_wrt_drop,
+    synthetic
 });
 
 impl_stable_hash_for!(struct hir::Generics {
@@ -180,6 +188,10 @@ impl_stable_hash_for!(struct hir::Generics {
     span
 });
 
+impl_stable_hash_for!(enum hir::SyntheticTyParamKind {
+    ImplTrait
+});
+
 impl_stable_hash_for!(struct hir::WhereClause {
     id,
     predicates
@@ -238,6 +250,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::Ty {
         hcx.while_hashing_hir_bodies(true, |hcx| {
             let hir::Ty {
                 id: _,
+                hir_id: _,
                 ref node,
                 ref span,
             } = *self;
@@ -691,7 +704,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem {
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
-            id,
+            id: _,
             hir_id: _,
             name,
             ref attrs,
@@ -700,7 +713,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::TraitItem {
         } = *self;
 
         hcx.hash_hir_item_like(attrs, |hcx| {
-            id.hash_stable(hcx, hasher);
             name.hash_stable(hcx, hasher);
             attrs.hash_stable(hcx, hasher);
             node.hash_stable(hcx, hasher);
@@ -725,7 +737,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem {
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
-            id,
+            id: _,
             hir_id: _,
             name,
             ref vis,
@@ -736,7 +748,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItem {
         } = *self;
 
         hcx.hash_hir_item_like(attrs, |hcx| {
-            id.hash_stable(hcx, hasher);
             name.hash_stable(hcx, hasher);
             vis.hash_stable(hcx, hasher);
             defaultness.hash_stable(hcx, hasher);
@@ -1160,6 +1171,25 @@ for hir::TraitCandidate {
     }
 }
 
+impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate {
+    type KeyType = (DefPathHash, Option<(DefPathHash, hir::ItemLocalId)>);
+
+    fn to_stable_hash_key(&self,
+                          hcx: &StableHashingContext<'gcx>)
+                          -> Self::KeyType {
+        let hir::TraitCandidate {
+            def_id,
+            import_id,
+        } = *self;
+
+        let import_id = import_id.map(|node_id| hcx.node_to_hir_id(node_id))
+                                 .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner),
+                                                hir_id.local_id));
+        (hcx.def_path_hash(def_id), import_id)
+    }
+}
+
+
 impl_stable_hash_for!(struct hir::Freevar {
     def,
     span
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 9b6613e4cae..4bda89690b7 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -28,10 +28,12 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> {
     name,
     source_info,
     internal,
+    lexical_scope,
     is_user_variable
 });
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref });
 impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup });
+impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, lint_node_id });
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>>
 for mir::Terminator<'gcx> {
@@ -75,6 +77,22 @@ for mir::Terminator<'gcx> {
     }
 }
 
+impl<'gcx, T> HashStable<StableHashingContext<'gcx>> for mir::ClearOnDecode<T>
+    where T: HashStable<StableHashingContext<'gcx>>
+{
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            mir::ClearOnDecode::Clear => {}
+            mir::ClearOnDecode::Set(ref value) => {
+                value.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Local {
     #[inline]
@@ -347,6 +365,26 @@ for mir::ProjectionElem<'gcx, V, T>
 }
 
 impl_stable_hash_for!(struct mir::VisibilityScopeData { span, parent_scope });
+impl_stable_hash_for!(struct mir::VisibilityScopeInfo {
+    lint_root, safety
+});
+
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Safety {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            mir::Safety::Safe |
+            mir::Safety::BuiltinUnsafe |
+            mir::Safety::FnUnsafe => {}
+            mir::Safety::ExplicitUnsafe(node_id) => {
+                node_id.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Operand<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 56ec6a65eb6..669e1ba773e 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -272,6 +272,8 @@ fn hash_token<'gcx, W: StableHasherResult>(token: &token::Token,
         token::Token::Dot |
         token::Token::DotDot |
         token::Token::DotDotDot |
+        token::Token::DotDotEq |
+        token::Token::DotEq |
         token::Token::Comma |
         token::Token::Semi |
         token::Token::Colon |
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index e3ecaae953a..fe060aaf426 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -463,7 +463,8 @@ impl_stable_hash_for!(struct ty::TypeParameterDef {
     index,
     has_default,
     object_lifetime_default,
-    pure_wrt_drop
+    pure_wrt_drop,
+    synthetic
 });
 
 impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
@@ -514,13 +515,8 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
     FnPtrAddrCast
 });
 
-impl_stable_hash_for!(enum ::middle::region::Scope {
-    Node(local_id),
-    Destruction(local_id),
-    CallSite(local_id),
-    Arguments(local_id),
-    Remainder(block_remainder)
-});
+impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx });
+impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
 
 impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {
     type KeyType = region::Scope;
diff --git a/src/librustc/infer/error_reporting/different_lifetimes.rs b/src/librustc/infer/error_reporting/different_lifetimes.rs
index 6c57130a995..ee30db26255 100644
--- a/src/librustc/infer/error_reporting/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/different_lifetimes.rs
@@ -18,6 +18,7 @@ use infer::region_inference::RegionResolutionError;
 use hir::map as hir_map;
 use middle::resolve_lifetime as rl;
 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
@@ -57,6 +58,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup));
 
         let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub));
+
         debug!("try_report_anon_anon_conflict: found_arg1={:?} sup={:?} br1={:?}",
                ty_sub,
                sup,
@@ -66,56 +68,70 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                sub,
                bregion_sub);
 
-        let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
-            (self.find_arg_with_region(sup, sup), self.find_arg_with_region(sub, sub)) {
+        let (ty_sup, ty_fndecl_sup) = ty_sup;
+        let (ty_sub, ty_fndecl_sub) = ty_sub;
 
-            let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) =
-                (sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first);
-            if self.is_self_anon(is_first_sup, scope_def_id_sup) ||
-               self.is_self_anon(is_first_sub, scope_def_id_sub) {
-                return false;
-            }
+        let AnonymousArgInfo { arg: anon_arg_sup, .. } =
+            or_false!(self.find_arg_with_region(sup, sup));
+        let AnonymousArgInfo { arg: anon_arg_sub, .. } =
+            or_false!(self.find_arg_with_region(sub, sub));
 
-            if self.is_return_type_anon(scope_def_id_sup, bregion_sup) ||
-               self.is_return_type_anon(scope_def_id_sub, bregion_sub) {
-                return false;
-            }
+        let sup_is_ret_type =
+            self.is_return_type_anon(scope_def_id_sup, bregion_sup, ty_fndecl_sup);
+        let sub_is_ret_type =
+            self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
 
-            if anon_arg_sup == anon_arg_sub {
-                (format!("this type was declared with multiple lifetimes..."),
-                 format!(" with one lifetime"),
-                 format!(" into the other"))
-            } else {
-                let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
-                    format!(" from `{}`", simple_name)
-                } else {
-                    format!("")
-                };
+        let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
+            format!(" from `{}`", simple_name)
+        } else {
+            format!("")
+        };
+
+        let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
+            format!(" into `{}`", simple_name)
+        } else {
+            format!("")
+        };
+
+
+        let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
+            (None, None) => {
+                let (main_label_1, span_label_1) = if ty_sup == ty_sub {
 
-                let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
-                    format!(" into `{}`", simple_name)
+                    (format!("this type is declared with multiple lifetimes..."),
+                     format!("...but data{} flows{} here",
+                             format!(" with one lifetime"),
+                             format!(" into the other")))
                 } else {
-                    format!("")
+                    (format!("these two types are declared with different lifetimes..."),
+                     format!("...but data{} flows{} here",
+                             span_label_var1,
+                             span_label_var2))
                 };
+                (ty_sup.span, ty_sub.span, main_label_1, span_label_1)
+            }
 
-                let span_label =
-                    format!("these two types are declared with different lifetimes...",);
-
-                (span_label, span_label_var1, span_label_var2)
+            (Some(ret_span), _) => {
+                (ty_sub.span,
+                 ret_span,
+                 format!("this parameter and the return type are declared \
+                          with different lifetimes...",),
+                 format!("...but data{} is returned here", span_label_var1))
+            }
+            (_, Some(ret_span)) => {
+                (ty_sup.span,
+                 ret_span,
+                 format!("this parameter and the return type are declared \
+                          with different lifetimes...",),
+                 format!("...but data{} is returned here", span_label_var1))
             }
-        } else {
-            debug!("no arg with anon region found");
-            debug!("try_report_anon_anon_conflict: is_suitable(sub) = {:?}",
-                   self.is_suitable_region(sub));
-            debug!("try_report_anon_anon_conflict: is_suitable(sup) = {:?}",
-                   self.is_suitable_region(sup));
-            return false;
         };
 
+
         struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
-            .span_label(ty_sup.span, main_label)
-            .span_label(ty_sub.span, format!(""))
-            .span_label(span, format!("...but data{} flows{} here", label1, label2))
+            .span_label(span_1, main_label)
+            .span_label(span_2, format!(""))
+            .span_label(span, span_label)
             .emit();
         return true;
     }
@@ -135,28 +151,32 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// ```
     /// The function returns the nested type corresponding to the anonymous region
     /// for e.g. `&u8` and Vec<`&u8`.
-    pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
+    pub fn find_anon_type(&self,
+                          region: Region<'tcx>,
+                          br: &ty::BoundRegion)
+                          -> Option<(&hir::Ty, &hir::FnDecl)> {
         if let Some(anon_reg) = self.is_suitable_region(region) {
             let def_id = anon_reg.def_id;
             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
-                let inputs: &[_] = match self.tcx.hir.get(node_id) {
+                let fndecl = match self.tcx.hir.get(node_id) {
                     hir_map::NodeItem(&hir::Item { node: hir::ItemFn(ref fndecl, ..), .. }) => {
-                        &fndecl.inputs
+                        &fndecl
                     }
                     hir_map::NodeTraitItem(&hir::TraitItem {
-                                               node: hir::TraitItemKind::Method(ref fndecl, ..), ..
-                                           }) => &fndecl.decl.inputs,
+                                               node: hir::TraitItemKind::Method(ref m, ..), ..
+                                           }) |
                     hir_map::NodeImplItem(&hir::ImplItem {
-                                              node: hir::ImplItemKind::Method(ref fndecl, ..), ..
-                                          }) => &fndecl.decl.inputs,
-
-                    _ => &[],
+                                              node: hir::ImplItemKind::Method(ref m, ..), ..
+                                          }) => &m.decl,
+                    _ => return None,
                 };
 
-                return inputs
+                return fndecl
+                           .inputs
                            .iter()
-                           .filter_map(|arg| self.find_component_for_bound_region(&**arg, br))
-                           .next();
+                           .filter_map(|arg| self.find_component_for_bound_region(arg, br))
+                           .next()
+                           .map(|ty| (ty, &**fndecl));
             }
         }
         None
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index a88e90caee3..3f22950fc77 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -72,6 +72,8 @@ use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
 use errors::{DiagnosticBuilder, DiagnosticStyledString};
 
+use rustc_data_structures::indexed_vec::Idx;
+
 mod note;
 
 mod need_type_info;
@@ -152,21 +154,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         return;
                     }
                 };
-                let scope_decorated_tag = match scope {
-                    region::Scope::Node(_) => tag,
-                    region::Scope::CallSite(_) => {
+                let scope_decorated_tag = match scope.data() {
+                    region::ScopeData::Node(_) => tag,
+                    region::ScopeData::CallSite(_) => {
                         "scope of call-site for function"
                     }
-                    region::Scope::Arguments(_) => {
+                    region::ScopeData::Arguments(_) => {
                         "scope of function body"
                     }
-                    region::Scope::Destruction(_) => {
+                    region::ScopeData::Destruction(_) => {
                         new_string = format!("destruction scope surrounding {}", tag);
                         &new_string[..]
                     }
-                    region::Scope::Remainder(r) => {
+                    region::ScopeData::Remainder(r) => {
                         new_string = format!("block suffix following statement {}",
-                                             r.first_statement_index);
+                                             r.first_statement_index.index());
                         &new_string[..]
                     }
                 };
@@ -333,11 +335,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             GenericBoundFailure(..) => true,
         };
 
-        if errors.iter().all(|e| is_bound_failure(e)) {
+
+        let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
             errors.clone()
         } else {
             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
-        }
+        };
+
+        // sort the errors by span, for better error message stability.
+        errors.sort_by_key(|u| match *u {
+            ConcreteFailure(ref sro, _, _) => sro.span(),
+            GenericBoundFailure(ref sro, _, _) => sro.span(),
+            SubSupConflict(ref rvo, _, _, _, _) => rvo.span(),
+        });
+        errors
     }
 
     /// Adds a note if the types come from similarly named crates
@@ -774,10 +785,44 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                     bound_kind: GenericKind<'tcx>,
                                     sub: Region<'tcx>)
     {
-        // FIXME: it would be better to report the first error message
-        // with the span of the parameter itself, rather than the span
-        // where the error was detected. But that span is not readily
-        // accessible.
+        // Attempt to obtain the span of the parameter so we can
+        // suggest adding an explicit lifetime bound to it.
+        let type_param_span = match (self.in_progress_tables, bound_kind) {
+            (Some(ref table), GenericKind::Param(ref param)) => {
+                let table = table.borrow();
+                table.local_id_root.and_then(|did| {
+                    let generics = self.tcx.generics_of(did);
+                    // Account for the case where `did` corresponds to `Self`, which doesn't have
+                    // the expected type argument.
+                    if generics.types.len() > 0 {
+                        let type_param = generics.type_param(param);
+                        let hir = &self.tcx.hir;
+                        hir.as_local_node_id(type_param.def_id).map(|id| {
+                            // Get the `hir::TyParam` to verify wether it already has any bounds.
+                            // We do this to avoid suggesting code that ends up as `T: 'a'b`,
+                            // instead we suggest `T: 'a + 'b` in that case.
+                            let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) {
+                                p.bounds.len() > 0
+                            } else {
+                                false
+                            };
+                            let sp = hir.span(id);
+                            // `sp` only covers `T`, change it so that it covers
+                            // `T:` when appropriate
+                            let sp = if has_lifetimes {
+                                sp.to(sp.next_point().next_point())
+                            } else {
+                                sp
+                            };
+                            (sp, has_lifetimes)
+                        })
+                    } else {
+                        None
+                    }
+                })
+            }
+            _ => None,
+        };
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) =>
@@ -799,6 +844,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             return;
         }
 
+        fn binding_suggestion<'tcx, S: fmt::Display>(err: &mut DiagnosticBuilder<'tcx>,
+                                                     type_param_span: Option<(Span, bool)>,
+                                                     bound_kind: GenericKind<'tcx>,
+                                                     sub: S) {
+            let consider = &format!("consider adding an explicit lifetime bound `{}: {}`...",
+                                    bound_kind,
+                                    sub);
+            if let Some((sp, has_lifetimes)) = type_param_span {
+                let tail = if has_lifetimes {
+                    " + "
+                } else {
+                    ""
+                };
+                let suggestion = format!("{}: {}{}", bound_kind, sub, tail);
+                err.span_suggestion_short(sp, consider, suggestion);
+            } else {
+                err.help(consider);
+            }
+        }
+
         let mut err = match *sub {
             ty::ReEarlyBound(_) |
             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
@@ -808,9 +873,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                E0309,
                                                "{} may not live long enough",
                                                labeled_user_string);
-                err.help(&format!("consider adding an explicit lifetime bound `{}: {}`...",
-                         bound_kind,
-                         sub));
+                binding_suggestion(&mut err, type_param_span, bound_kind, sub);
                 err
             }
 
@@ -821,9 +884,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                E0310,
                                                "{} may not live long enough",
                                                labeled_user_string);
-                err.help(&format!("consider adding an explicit lifetime \
-                                   bound `{}: 'static`...",
-                                  bound_kind));
+                binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
                 err
             }
 
diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs
index a3bbdab497a..80fb4ce8e03 100644
--- a/src/librustc/infer/error_reporting/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs
@@ -35,15 +35,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // only introduced anonymous regions in parameters) as well as a
         // version new_ty of its type where the anonymous region is replaced
         // with the named one.//scope_def_id
-        let (named, anon_arg_info, region_info) =
+        let (named, anon, anon_arg_info, region_info) =
             if self.is_named_region(sub) && self.is_suitable_region(sup).is_some() &&
                self.find_arg_with_region(sup, sub).is_some() {
                 (sub,
+                 sup,
                  self.find_arg_with_region(sup, sub).unwrap(),
                  self.is_suitable_region(sup).unwrap())
             } else if self.is_named_region(sup) && self.is_suitable_region(sub).is_some() &&
                       self.find_arg_with_region(sub, sup).is_some() {
                 (sup,
+                 sub,
                  self.find_arg_with_region(sub, sup).unwrap(),
                  self.is_suitable_region(sub).unwrap())
             } else {
@@ -76,33 +78,29 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             return false;
         }
 
-        if self.is_return_type_anon(scope_def_id, br) {
-            debug!("try_report_named_anon_conflict: is_return_type_anon({:?}, {:?}) = true",
-                   scope_def_id,
-                   br);
-            return false;
-        } else if self.is_self_anon(is_first, scope_def_id) {
-            debug!("try_report_named_anon_conflict: is_self_anon({:?}, {:?}) = true",
-                   is_first,
-                   scope_def_id);
-            return false;
+        if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
+            if self.is_return_type_anon(scope_def_id, br, fndecl).is_some() ||
+               self.is_self_anon(is_first, scope_def_id) {
+                return false;
+            }
+        }
+
+        let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
+            (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
         } else {
-            let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
-                (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
-            } else {
-                ("parameter type".to_owned(), "type".to_owned())
-            };
+            ("parameter type".to_owned(), "type".to_owned())
+        };
+
+        struct_span_err!(self.tcx.sess,
+                         span,
+                         E0621,
+                         "explicit lifetime required in {}",
+                         error_var)
+                .span_label(arg.pat.span,
+                            format!("consider changing {} to `{}`", span_label_var, new_ty))
+                .span_label(span, format!("lifetime `{}` required", named))
+                .emit();
+        return true;
 
-            struct_span_err!(self.tcx.sess,
-                             span,
-                             E0621,
-                             "explicit lifetime required in {}",
-                             error_var)
-                    .span_label(arg.pat.span,
-                                format!("consider changing {} to `{}`", span_label_var, new_ty))
-                    .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 94faec464b2..47db3f1b792 100644
--- a/src/librustc/infer/error_reporting/util.rs
+++ b/src/librustc/infer/error_reporting/util.rs
@@ -15,6 +15,7 @@ use infer::InferCtxt;
 use ty::{self, Region, Ty};
 use hir::def_id::DefId;
 use hir::map as hir_map;
+use syntax_pos::Span;
 
 macro_rules! or_false {
      ($v:expr) => {
@@ -163,7 +164,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // Here, we check for the case where the anonymous region
     // is in the return type.
     // FIXME(#42703) - Need to handle certain cases here.
-    pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool {
+    pub fn is_return_type_anon(&self,
+                               scope_def_id: DefId,
+                               br: ty::BoundRegion,
+                               decl: &hir::FnDecl)
+                               -> Option<Span> {
         let ret_ty = self.tcx.type_of(scope_def_id);
         match ret_ty.sty {
             ty::TyFnDef(_, _) => {
@@ -171,12 +176,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 let late_bound_regions = self.tcx
                     .collect_referenced_late_bound_regions(&sig.output());
                 if late_bound_regions.iter().any(|r| *r == br) {
-                    return true;
+                    return Some(decl.output.span());
                 }
             }
             _ => {}
         }
-        false
+        None
     }
     // Here we check for the case where anonymous region
     // corresponds to self and if yes, we display E0312.
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index cd39ef70946..1e90aa47267 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -111,7 +111,6 @@ pub mod middle {
     pub mod dataflow;
     pub mod dead;
     pub mod dependency_format;
-    pub mod effect;
     pub mod entry;
     pub mod exported_symbols;
     pub mod free_region;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 21852468146..5fe75d8ca71 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -30,7 +30,7 @@ declare_lint! {
 
 declare_lint! {
     pub UNUSED_EXTERN_CRATES,
-    Warn,
+    Allow,
     "extern crates that are never used"
 }
 
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index 21dfd3267df..4bc37747f2a 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -384,6 +384,11 @@ impl LintLevelMap {
             self.sets.get_lint_level(lint, *idx, None)
         })
     }
+
+    /// Returns if this `id` has lint level information.
+    pub fn lint_level_set(&self, id: HirId) -> Option<u32> {
+        self.id_to_set.get(&id).cloned()
+    }
 }
 
 impl<'gcx> HashStable<StableHashingContext<'gcx>> for LintLevelMap {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index de647913f0f..a97bfa05369 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -267,6 +267,8 @@ pub trait CrateStore {
     fn export_macros_untracked(&self, cnum: CrateNum);
     fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind;
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol;
+    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
     fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
     fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
     fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
@@ -336,6 +338,10 @@ impl CrateStore for DummyCrateStore {
     fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
     fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") }
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol {
+        bug!("crate_disambiguator")
+    }
+    fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 66a425a2d47..a9d9f6f28ec 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -553,9 +553,22 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         if self.should_warn_about_item(item) {
+            // For items that have a definition with a signature followed by a
+            // block, point only at the signature.
+            let span = match item.node {
+                hir::ItemFn(..) |
+                hir::ItemMod(..) |
+                hir::ItemEnum(..) |
+                hir::ItemStruct(..) |
+                hir::ItemUnion(..) |
+                hir::ItemTrait(..) |
+                hir::ItemDefaultImpl(..) |
+                hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
+                _ => item.span,
+            };
             self.warn_dead_code(
                 item.id,
-                item.span,
+                span,
                 item.name,
                 item.node.descriptive_variant()
             );
@@ -570,8 +583,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                      g: &'tcx hir::Generics,
                      id: ast::NodeId) {
         if self.should_warn_about_variant(&variant.node) {
-            self.warn_dead_code(variant.node.data.id(), variant.span,
-                                variant.node.name, "variant");
+            self.warn_dead_code(variant.node.data.id(), variant.span, variant.node.name, "variant");
         } else {
             intravisit::walk_variant(self, variant, g, id);
         }
@@ -596,15 +608,17 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
         match impl_item.node {
             hir::ImplItemKind::Const(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
-                    self.warn_dead_code(impl_item.id, impl_item.span,
-                                        impl_item.name, "associated const");
+                    self.warn_dead_code(impl_item.id,
+                                        impl_item.span,
+                                        impl_item.name,
+                                        "associated const");
                 }
                 self.visit_nested_body(body_id)
             }
             hir::ImplItemKind::Method(_, body_id) => {
                 if !self.symbol_is_live(impl_item.id, None) {
-                    self.warn_dead_code(impl_item.id, impl_item.span,
-                                        impl_item.name, "method");
+                    let span = self.tcx.sess.codemap().def_span(impl_item.span);
+                    self.warn_dead_code(impl_item.id, span, impl_item.name, "method");
                 }
                 self.visit_nested_body(body_id)
             }
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 1c7d0b76a64..db0ecb6aa5e 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -112,52 +112,61 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return Vec::new();
     }
 
-    match ty {
-        // If the global prefer_dynamic switch is turned off, first attempt
-        // static linkage (this can fail).
-        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
-        }
+    let preferred_linkage = match ty {
+        // cdylibs must have all static dependencies.
+        config::CrateTypeCdylib => Linkage::Static,
+
+        // Generating a dylib without `-C prefer-dynamic` means that we're going
+        // to try to eagerly statically link all dependencies. This is normally
+        // done for end-product dylibs, not intermediate products.
+        config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => Linkage::Static,
+        config::CrateTypeDylib => Linkage::Dynamic,
+
+        // If the global prefer_dynamic switch is turned off, or the final
+        // executable will be statically linked, prefer static crate linkage.
+        config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic ||
+            sess.crt_static() => Linkage::Static,
+        config::CrateTypeExecutable => Linkage::Dynamic,
+
+        // proc-macro crates are required to be dylibs, and they're currently
+        // required to link to libsyntax as well.
+        config::CrateTypeProcMacro => Linkage::Dynamic,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib => return Vec::new(),
-
-        // Staticlibs and cdylibs must have all static dependencies. If any fail
-        // to be found, we generate some nice pretty errors.
-        config::CrateTypeStaticlib |
-        config::CrateTypeCdylib => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
+        config::CrateTypeRlib => Linkage::NotLinked,
+
+        // staticlibs must have all static dependencies.
+        config::CrateTypeStaticlib => Linkage::Static,
+    };
+
+    if preferred_linkage == Linkage::NotLinked {
+        // If the crate is not linked, there are no link-time dependencies.
+        return Vec::new();
+    }
+
+    if preferred_linkage == Linkage::Static {
+        // Attempt static linkage first. For dylibs and executables, we may be
+        // able to retry below with dynamic linkage.
+        if let Some(v) = attempt_static(tcx) {
+            return v;
+        }
+
+        // Staticlibs, cdylibs, and static executables must have all static
+        // dependencies. If any are not found, generate some nice pretty errors.
+        if ty == config::CrateTypeCdylib || ty == config::CrateTypeStaticlib ||
+                (ty == config::CrateTypeExecutable && sess.crt_static() &&
+                !sess.target.target.options.crt_static_allows_dylibs) {
             for &cnum in tcx.crates().iter() {
                 if tcx.dep_kind(cnum).macros_only() { continue }
                 let src = tcx.used_crate_source(cnum);
                 if src.rlib.is_some() { continue }
-                sess.err(&format!("dependency `{}` not found in rlib format",
+                sess.err(&format!("crate `{}` required to be available in rlib format, \
+                                  but was not found in this form",
                                   tcx.crate_name(cnum)));
             }
             return Vec::new();
         }
-
-        // Generating a dylib without `-C prefer-dynamic` means that we're going
-        // to try to eagerly statically link all dependencies. This is normally
-        // done for end-product dylibs, not intermediate products.
-        config::CrateTypeDylib if !sess.opts.cg.prefer_dynamic => {
-            if let Some(v) = attempt_static(tcx) {
-                return v;
-            }
-        }
-
-        // Everything else falls through below. This will happen either with the
-        // `-C prefer-dynamic` or because we're a proc-macro crate. Note that
-        // proc-macro crates are required to be dylibs, and they're currently
-        // required to link to libsyntax as well.
-        config::CrateTypeExecutable |
-        config::CrateTypeDylib |
-        config::CrateTypeProcMacro => {},
     }
 
     let mut formats = FxHashMap();
@@ -236,10 +245,9 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     Linkage::Static => "rlib",
                     _ => "dylib",
                 };
-                let name = tcx.crate_name(cnum);
-                sess.err(&format!("crate `{}` required to be available in {}, \
-                                  but it was not available in this form",
-                                  name, kind));
+                sess.err(&format!("crate `{}` required to be available in {} format, \
+                                  but was not found in this form",
+                                  tcx.crate_name(cnum), kind));
             }
         }
     }
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
deleted file mode 100644
index 7290353e48b..00000000000
--- a/src/librustc/middle/effect.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2012-2013 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.
-
-//! Enforces the Rust effect system. Currently there is just one effect,
-//! `unsafe`.
-use self::RootUnsafeContext::*;
-
-use ty::{self, TyCtxt};
-use lint;
-use lint::builtin::UNUSED_UNSAFE;
-
-use hir::def::Def;
-use hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap};
-use hir::{self, PatKind};
-use syntax::ast;
-use syntax_pos::Span;
-use util::nodemap::FxHashSet;
-
-#[derive(Copy, Clone)]
-struct UnsafeContext {
-    push_unsafe_count: usize,
-    root: RootUnsafeContext,
-}
-
-impl UnsafeContext {
-    fn new(root: RootUnsafeContext) -> UnsafeContext {
-        UnsafeContext { root: root, push_unsafe_count: 0 }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq)]
-enum RootUnsafeContext {
-    SafeContext,
-    UnsafeFn,
-    UnsafeBlock(ast::NodeId),
-}
-
-struct EffectCheckVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    tables: &'a ty::TypeckTables<'tcx>,
-    body_id: hir::BodyId,
-
-    /// Whether we're in an unsafe context.
-    unsafe_context: UnsafeContext,
-    used_unsafe: FxHashSet<ast::NodeId>,
-}
-
-impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
-    fn require_unsafe_ext(&mut self, node_id: ast::NodeId, span: Span,
-                          description: &str, is_lint: bool) {
-        if self.unsafe_context.push_unsafe_count > 0 { return; }
-        match self.unsafe_context.root {
-            SafeContext => {
-                if is_lint {
-                    self.tcx.lint_node(lint::builtin::SAFE_EXTERN_STATICS,
-                                       node_id,
-                                       span,
-                                       &format!("{} requires unsafe function or \
-                                                 block (error E0133)", description));
-                } else {
-                    // Report an error.
-                    struct_span_err!(
-                        self.tcx.sess, span, E0133,
-                        "{} requires unsafe function or block", description)
-                        .span_label(span, description)
-                        .emit();
-                }
-            }
-            UnsafeBlock(block_id) => {
-                // OK, but record this.
-                debug!("effect: recording unsafe block as used: {}", block_id);
-                self.used_unsafe.insert(block_id);
-            }
-            UnsafeFn => {}
-        }
-    }
-
-    fn require_unsafe(&mut self, span: Span, description: &str) {
-        self.require_unsafe_ext(ast::DUMMY_NODE_ID, span, description, false)
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_nested_body(&mut self, body: hir::BodyId) {
-        let old_tables = self.tables;
-        let old_body_id = self.body_id;
-        self.tables = self.tcx.body_tables(body);
-        self.body_id = body;
-        let body = self.tcx.hir.body(body);
-        self.visit_body(body);
-        self.tables = old_tables;
-        self.body_id = old_body_id;
-    }
-
-    fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
-                body_id: hir::BodyId, span: Span, id: ast::NodeId) {
-
-        let (is_item_fn, is_unsafe_fn) = match fn_kind {
-            FnKind::ItemFn(_, _, unsafety, ..) =>
-                (true, unsafety == hir::Unsafety::Unsafe),
-            FnKind::Method(_, sig, ..) =>
-                (true, sig.unsafety == hir::Unsafety::Unsafe),
-            _ => (false, false),
-        };
-
-        let old_unsafe_context = self.unsafe_context;
-        if is_unsafe_fn {
-            self.unsafe_context = UnsafeContext::new(UnsafeFn)
-        } else if is_item_fn {
-            self.unsafe_context = UnsafeContext::new(SafeContext)
-        }
-
-        intravisit::walk_fn(self, fn_kind, fn_decl, body_id, span, id);
-
-        self.unsafe_context = old_unsafe_context
-    }
-
-    fn visit_block(&mut self, block: &'tcx hir::Block) {
-        let old_unsafe_context = self.unsafe_context;
-        match block.rules {
-            hir::UnsafeBlock(source) => {
-                // By default only the outermost `unsafe` block is
-                // "used" and so nested unsafe blocks are pointless
-                // (the inner ones are unnecessary and we actually
-                // warn about them). As such, there are two cases when
-                // we need to create a new context, when we're
-                // - outside `unsafe` and found a `unsafe` block
-                //   (normal case)
-                // - inside `unsafe`, found an `unsafe` block
-                //   created internally to the compiler
-                //
-                // The second case is necessary to ensure that the
-                // compiler `unsafe` blocks don't accidentally "use"
-                // external blocks (e.g. `unsafe { println("") }`,
-                // expands to `unsafe { ... unsafe { ... } }` where
-                // the inner one is compiler generated).
-                if self.unsafe_context.root == SafeContext || source == hir::CompilerGenerated {
-                    self.unsafe_context.root = UnsafeBlock(block.id)
-                }
-            }
-            hir::PushUnsafeBlock(..) => {
-                self.unsafe_context.push_unsafe_count =
-                    self.unsafe_context.push_unsafe_count.checked_add(1).unwrap();
-            }
-            hir::PopUnsafeBlock(..) => {
-                self.unsafe_context.push_unsafe_count =
-                    self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap();
-            }
-            hir::DefaultBlock => {}
-        }
-
-        intravisit::walk_block(self, block);
-
-        self.unsafe_context = old_unsafe_context;
-
-        // Don't warn about generated blocks, that'll just pollute the output.
-        match block.rules {
-            hir::UnsafeBlock(hir::UserProvided) => {}
-            _ => return,
-        }
-        if self.used_unsafe.contains(&block.id) {
-            return
-        }
-
-        /// Return the NodeId for an enclosing scope that is also `unsafe`
-        fn is_enclosed(tcx: TyCtxt,
-                       used_unsafe: &FxHashSet<ast::NodeId>,
-                       id: ast::NodeId) -> Option<(String, ast::NodeId)> {
-            let parent_id = tcx.hir.get_parent_node(id);
-            if parent_id != id {
-                if used_unsafe.contains(&parent_id) {
-                    Some(("block".to_string(), parent_id))
-                } else if let Some(hir::map::NodeItem(&hir::Item {
-                    node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
-                    ..
-                })) = tcx.hir.find(parent_id) {
-                    Some(("fn".to_string(), parent_id))
-                } else {
-                    is_enclosed(tcx, used_unsafe, parent_id)
-                }
-            } else {
-                None
-            }
-        }
-
-        let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE,
-                                                    block.id,
-                                                    block.span,
-                                                    "unnecessary `unsafe` block");
-        db.span_label(block.span, "unnecessary `unsafe` block");
-        if let Some((kind, id)) = is_enclosed(self.tcx, &self.used_unsafe, block.id) {
-            db.span_note(self.tcx.hir.span(id),
-                         &format!("because it's nested under this `unsafe` {}", kind));
-        }
-        db.emit();
-    }
-
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
-        match expr.node {
-            hir::ExprMethodCall(..) => {
-                let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id();
-                let sig = self.tcx.fn_sig(def_id);
-                debug!("effect: method call case, signature is {:?}",
-                        sig);
-
-                if sig.0.unsafety == hir::Unsafety::Unsafe {
-                    self.require_unsafe(expr.span,
-                                        "invocation of unsafe method")
-                }
-            }
-            hir::ExprCall(ref base, _) => {
-                let base_type = self.tables.expr_ty_adjusted(base);
-                debug!("effect: call case, base type is {:?}",
-                        base_type);
-                match base_type.sty {
-                    ty::TyFnDef(..) | ty::TyFnPtr(_) => {
-                        if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
-                            self.require_unsafe(expr.span, "call to unsafe function")
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            hir::ExprUnary(hir::UnDeref, ref base) => {
-                let base_type = self.tables.expr_ty_adjusted(base);
-                debug!("effect: unary case, base type is {:?}",
-                        base_type);
-                if let ty::TyRawPtr(_) = base_type.sty {
-                    self.require_unsafe(expr.span, "dereference of raw pointer")
-                }
-            }
-            hir::ExprInlineAsm(..) => {
-                self.require_unsafe(expr.span, "use of inline assembly");
-            }
-            hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
-                if let Def::Static(def_id, mutbl) = path.def {
-                    if mutbl {
-                        self.require_unsafe(expr.span, "use of mutable static");
-                    } else if match self.tcx.hir.get_if_local(def_id) {
-                        Some(hir::map::NodeForeignItem(..)) => true,
-                        Some(..) => false,
-                        None => self.tcx.is_foreign_item(def_id),
-                    } {
-                        self.require_unsafe_ext(expr.id, expr.span, "use of extern static", true);
-                    }
-                }
-            }
-            hir::ExprField(ref base_expr, field) => {
-                if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty {
-                    if adt.is_union() {
-                        self.require_unsafe(field.span, "access to union field");
-                    }
-                }
-            }
-            hir::ExprAssign(ref lhs, ref rhs) => {
-                if let hir::ExprField(ref base_expr, field) = lhs.node {
-                    if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty {
-                        if adt.is_union() {
-                            let field_ty = self.tables.expr_ty_adjusted(lhs);
-                            let owner_def_id = self.tcx.hir.body_owner_def_id(self.body_id);
-                            let param_env = self.tcx.param_env(owner_def_id);
-                            if field_ty.moves_by_default(self.tcx, param_env, field.span) {
-                                self.require_unsafe(field.span,
-                                                    "assignment to non-`Copy` union field");
-                            }
-                            // Do not walk the field expr again.
-                            intravisit::walk_expr(self, base_expr);
-                            intravisit::walk_expr(self, rhs);
-                            return
-                        }
-                    }
-                }
-            }
-            _ => {}
-        }
-
-        intravisit::walk_expr(self, expr);
-    }
-
-    fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
-        if let PatKind::Struct(_, ref fields, _) = pat.node {
-            if let ty::TyAdt(adt, ..) = self.tables.pat_ty(pat).sty {
-                if adt.is_union() {
-                    for field in fields {
-                        self.require_unsafe(field.span, "matching on union field");
-                    }
-                }
-            }
-        }
-
-        intravisit::walk_pat(self, pat);
-    }
-}
-
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    let mut visitor = EffectCheckVisitor {
-        tcx,
-        tables: &ty::TypeckTables::empty(None),
-        body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID },
-        unsafe_context: UnsafeContext::new(SafeContext),
-        used_unsafe: FxHashSet(),
-    };
-
-    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
-}
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index 4de86b66916..49a241b86e0 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -117,7 +117,7 @@ impl<'a, 'gcx, 'tcx> RegionRelations<'a, 'gcx, 'tcx> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct FreeRegionMap<'tcx> {
     // Stores the relation `a < b`, where `a` and `b` are regions.
     //
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 0c0b9697338..679c4f17a6c 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -280,8 +280,6 @@ language_item_table! {
     EqTraitLangItem,                 "eq",                      eq_trait;
     OrdTraitLangItem,                "ord",                     ord_trait;
 
-    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;
-
     // A number of panic-related lang items. The `panic` item corresponds to
     // divide-by-zero and various panic cases with `match`. The
     // `panic_bounds_check` item is for indexing arrays.
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index fa29dda86dd..55d0c6b4c66 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -310,7 +310,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             hir_map::NodeVariant(_) |
             hir_map::NodeStructCtor(_) |
             hir_map::NodeField(_) |
-            hir_map::NodeTy(_) => {}
+            hir_map::NodeTy(_) |
+            hir_map::NodeMacroDef(_) => {}
             _ => {
                 bug!("found unexpected thingy in worklist: {}",
                      self.tcx.hir.node_to_string(search_item))
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 6cce7447669..59c9e8b4c43 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -18,6 +18,7 @@ use ich::{StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
 use ty;
 
+use std::fmt;
 use std::mem;
 use std::rc::Rc;
 use syntax::codemap;
@@ -31,6 +32,7 @@ use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
 use mir::transform::MirSource;
+use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 
@@ -95,8 +97,24 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
 /// placate the same deriving in `ty::FreeRegion`, but we may want to
 /// actually attach a more meaningful ordering to scopes than the one
 /// generated via deriving here.
+///
+/// Scope is a bit-packed to save space - if `code` is SCOPE_DATA_REMAINDER_MAX
+/// or less, it is a `ScopeData::Remainder`, otherwise it is a type specified
+/// by the bitpacking.
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
+pub struct Scope {
+    pub(crate) id: hir::ItemLocalId,
+    pub(crate) code: u32
+}
+
+const SCOPE_DATA_NODE: u32 = !0;
+const SCOPE_DATA_CALLSITE: u32 = !1;
+const SCOPE_DATA_ARGUMENTS: u32 = !2;
+const SCOPE_DATA_DESTRUCTION: u32 = !3;
+const SCOPE_DATA_REMAINDER_MAX: u32 = !4;
+
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
-pub enum Scope {
+pub enum ScopeData {
     Node(hir::ItemLocalId),
 
     // Scope of the call-site for a function or closure
@@ -135,7 +153,90 @@ pub enum Scope {
          RustcDecodable, Debug, Copy)]
 pub struct BlockRemainder {
     pub block: hir::ItemLocalId,
-    pub first_statement_index: u32,
+    pub first_statement_index: FirstStatementIndex,
+}
+
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
+         RustcDecodable, Copy)]
+pub struct FirstStatementIndex { pub idx: u32 }
+
+impl Idx for FirstStatementIndex {
+    fn new(idx: usize) -> Self {
+        assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize);
+        FirstStatementIndex { idx: idx as u32 }
+    }
+
+    fn index(self) -> usize {
+        self.idx as usize
+    }
+}
+
+impl fmt::Debug for FirstStatementIndex {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.index(), formatter)
+    }
+}
+
+impl From<ScopeData> for Scope {
+    #[inline]
+    fn from(scope_data: ScopeData) -> Self {
+        let (id, code) = match scope_data {
+            ScopeData::Node(id) => (id, SCOPE_DATA_NODE),
+            ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE),
+            ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS),
+            ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION),
+            ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32)
+        };
+        Self { id, code }
+    }
+}
+
+impl fmt::Debug for Scope {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.data(), formatter)
+    }
+}
+
+#[allow(non_snake_case)]
+impl Scope {
+    #[inline]
+    pub fn data(self) -> ScopeData {
+        match self.code {
+            SCOPE_DATA_NODE => ScopeData::Node(self.id),
+            SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id),
+            SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id),
+            SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
+            idx => ScopeData::Remainder(BlockRemainder {
+                block: self.id,
+                first_statement_index: FirstStatementIndex { idx }
+            })
+        }
+    }
+
+    #[inline]
+    pub fn Node(id: hir::ItemLocalId) -> Self {
+        Self::from(ScopeData::Node(id))
+    }
+
+    #[inline]
+    pub fn CallSite(id: hir::ItemLocalId) -> Self {
+        Self::from(ScopeData::CallSite(id))
+    }
+
+    #[inline]
+    pub fn Arguments(id: hir::ItemLocalId) -> Self {
+        Self::from(ScopeData::Arguments(id))
+    }
+
+    #[inline]
+    pub fn Destruction(id: hir::ItemLocalId) -> Self {
+        Self::from(ScopeData::Destruction(id))
+    }
+
+    #[inline]
+    pub fn Remainder(r: BlockRemainder) -> Self {
+        Self::from(ScopeData::Remainder(r))
+    }
 }
 
 impl Scope {
@@ -144,16 +245,7 @@ impl Scope {
     /// NB: likely to be replaced as API is refined; e.g. pnkfelix
     /// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
     pub fn item_local_id(&self) -> hir::ItemLocalId {
-        match *self {
-            Scope::Node(id) => id,
-
-            // These cases all return rough approximations to the
-            // precise scope denoted by `self`.
-            Scope::Remainder(br) => br.block,
-            Scope::Destruction(id) |
-            Scope::CallSite(id) |
-            Scope::Arguments(id) => id,
-        }
+        self.id
     }
 
     pub fn node_id(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> ast::NodeId {
@@ -177,7 +269,7 @@ impl Scope {
             return DUMMY_SP;
         }
         let span = tcx.hir.span(node_id);
-        if let Scope::Remainder(r) = *self {
+        if let ScopeData::Remainder(r) = self.data() {
             if let hir::map::NodeBlock(ref blk) = tcx.hir.get(node_id) {
                 // Want span for scope starting after the
                 // indexed statement and ending at end of
@@ -187,7 +279,7 @@ impl Scope {
                 // (This is the special case aluded to in the
                 // doc-comment for this method)
 
-                let stmt_span = blk.stmts[r.first_statement_index as usize].span;
+                let stmt_span = blk.stmts[r.first_statement_index.index()].span;
 
                 // To avoid issues with macro-generated spans, the span
                 // of the statement must be nested in that of the block.
@@ -201,7 +293,7 @@ impl Scope {
 }
 
 /// The region scope tree encodes information about region relationships.
-#[derive(Default)]
+#[derive(Default, Debug)]
 pub struct ScopeTree {
     /// If not empty, this body is the root of this region hierarchy.
     root_body: Option<hir::HirId>,
@@ -387,7 +479,7 @@ impl<'tcx> ScopeTree {
         }
 
         // record the destruction scopes for later so we can query them
-        if let Scope::Destruction(n) = child {
+        if let ScopeData::Destruction(n) = child.data() {
             self.destruction_scopes.insert(n, child);
         }
     }
@@ -482,8 +574,8 @@ impl<'tcx> ScopeTree {
         let mut id = Scope::Node(expr_id);
 
         while let Some(&p) = self.parent_map.get(&id) {
-            match p {
-                Scope::Destruction(..) => {
+            match p.data() {
+                ScopeData::Destruction(..) => {
                     debug!("temporary_scope({:?}) = {:?} [enclosing]",
                            expr_id, id);
                     return Some(id);
@@ -573,9 +665,9 @@ impl<'tcx> ScopeTree {
             // infer::region_inference for more details.
             let a_root_scope = a_ancestors[a_index];
             let b_root_scope = a_ancestors[a_index];
-            return match (a_root_scope, b_root_scope) {
-                (Scope::Destruction(a_root_id),
-                 Scope::Destruction(b_root_id)) => {
+            return match (a_root_scope.data(), b_root_scope.data()) {
+                (ScopeData::Destruction(a_root_id),
+                 ScopeData::Destruction(b_root_id)) => {
                     if self.closure_is_enclosed_by(a_root_id, b_root_id) {
                         // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
                         scope_b
@@ -764,7 +856,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
                 visitor.enter_scope(
                     Scope::Remainder(BlockRemainder {
                         block: blk.hir_id.local_id,
-                        first_statement_index: i as u32
+                        first_statement_index: FirstStatementIndex::new(i)
                     })
                 );
                 visitor.cx.var_parent = visitor.cx.parent;
@@ -915,8 +1007,10 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
             // Keep traversing up while we can.
             match visitor.scope_tree.parent_map.get(&scope) {
                 // Don't cross from closure bodies to their parent.
-                Some(&Scope::CallSite(_)) => break,
-                Some(&superscope) => scope = superscope,
+                Some(&superscope) => match superscope.data() {
+                    ScopeData::CallSite(_) => break,
+                    _ => scope = superscope
+                },
                 None => break
             }
         }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 2d201e5935e..d0c5460fa97 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -46,14 +46,16 @@ pub enum Region {
 }
 
 impl Region {
-    fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) {
+    fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef)
+        -> (hir::LifetimeName, Region)
+    {
         let i = *index;
         *index += 1;
         let def_id = hir_map.local_def_id(def.lifetime.id);
         (def.lifetime.name, Region::EarlyBound(i, def_id))
     }
 
-    fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (ast::Name, Region) {
+    fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
         let depth = ty::DebruijnIndex::new(1);
         let def_id = hir_map.local_def_id(def.lifetime.id);
         (def.lifetime.name, Region::LateBound(depth, def_id))
@@ -198,7 +200,7 @@ enum Scope<'a> {
     /// it should be shifted by the number of `Binder`s in between the
     /// declaration `Binder` and the location it's referenced from.
     Binder {
-        lifetimes: FxHashMap<ast::Name, Region>,
+        lifetimes: FxHashMap<hir::LifetimeName, Region>,
         s: ScopeRef<'a>
     },
 
@@ -443,7 +445,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
     fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
         for (i, segment) in path.segments.iter().enumerate() {
             let depth = path.segments.len() - i - 1;
-            self.visit_segment_parameters(path.def, depth, &segment.parameters);
+            if let Some(ref parameters) = segment.parameters {
+                self.visit_segment_parameters(path.def, depth, parameters);
+            }
         }
     }
 
@@ -654,7 +658,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, body: &hir::Body) {
 
                 Scope::Binder { ref lifetimes, s } => {
                     // FIXME (#24278): non-hygienic comparison
-                    if let Some(def) = lifetimes.get(&label) {
+                    if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
                         let node_id = hir_map.as_local_node_id(def.id().unwrap())
                                              .unwrap();
 
@@ -692,7 +696,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
                                 Set1::Empty => "BaseDefault".to_string(),
                                 Set1::One(Region::Static) => "'static".to_string(),
                                 Set1::One(Region::EarlyBound(i, _)) => {
-                                    generics.lifetimes[i as usize].lifetime.name.to_string()
+                                    generics.lifetimes[i as usize].lifetime.name.name().to_string()
                                 }
                                 Set1::One(_) => bug!(),
                                 Set1::Many => "Ambiguous".to_string(),
@@ -714,7 +718,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
 /// for each type parameter.
 fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
                                      -> Vec<ObjectLifetimeDefault> {
-    fn add_bounds(set: &mut Set1<ast::Name>, bounds: &[hir::TyParamBound]) {
+    fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) {
         for bound in bounds {
             if let hir::RegionTyParamBound(ref lifetime) = *bound {
                 set.insert(lifetime.name);
@@ -754,7 +758,7 @@ fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
         match set {
             Set1::Empty => Set1::Empty,
             Set1::One(name) => {
-                if name == "'static" {
+                if name == hir::LifetimeName::Static {
                     Set1::One(Region::Static)
                 } else {
                     generics.lifetimes.iter().enumerate().find(|&(_, def)| {
@@ -922,7 +926,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             self.insert_lifetime(lifetime_ref, def);
         } else {
             struct_span_err!(self.sess, lifetime_ref.span, E0261,
-                "use of undeclared lifetime name `{}`", lifetime_ref.name)
+                "use of undeclared lifetime name `{}`", lifetime_ref.name.name())
                 .span_label(lifetime_ref.span, "undeclared lifetime")
                 .emit();
         }
@@ -1422,13 +1426,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             let lifetime_i = &lifetimes[i];
 
             for lifetime in lifetimes {
-                if lifetime.lifetime.is_static() {
-                    let lifetime = lifetime.lifetime;
-                    let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
-                                  "invalid lifetime parameter name: `{}`", lifetime.name);
-                    err.span_label(lifetime.span,
-                                   format!("{} is a reserved lifetime name", lifetime.name));
-                    err.emit();
+                match lifetime.lifetime.name {
+                    hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
+                        let lifetime = lifetime.lifetime;
+                        let name = lifetime.name.name();
+                        let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
+                                      "invalid lifetime parameter name: `{}`", name);
+                        err.span_label(lifetime.span,
+                                       format!("{} is a reserved lifetime name", name));
+                        err.emit();
+                    }
+                    hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {}
                 }
             }
 
@@ -1439,7 +1447,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
                     struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263,
                                      "lifetime name `{}` declared twice in the same scope",
-                                     lifetime_j.lifetime.name)
+                                     lifetime_j.lifetime.name.name())
                         .span_label(lifetime_j.lifetime.span,
                                     "declared twice")
                         .span_label(lifetime_i.lifetime.span,
@@ -1452,15 +1460,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
 
             for bound in &lifetime_i.bounds {
-                if !bound.is_static() {
-                    self.resolve_lifetime_ref(bound);
-                } else {
-                    self.insert_lifetime(bound, Region::Static);
-                    self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span),
-                        &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name))
-                        .help(&format!("you can use the `'static` lifetime directly, in place \
-                                        of `{}`", lifetime_i.lifetime.name))
-                        .emit();
+                match bound.name {
+                    hir::LifetimeName::Underscore => {
+                        let mut err = struct_span_err!(self.sess, bound.span, E0637,
+                            "invalid lifetime bound name: `'_`");
+                        err.span_label(bound.span, "`'_` is a reserved lifetime name");
+                        err.emit();
+                    }
+                    hir::LifetimeName::Static => {
+                        self.insert_lifetime(bound, Region::Static);
+                        self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span),
+                            &format!("unnecessary lifetime parameter `{}`",
+                                    lifetime_i.lifetime.name.name()))
+                            .help(&format!(
+                                "you can use the `'static` lifetime directly, in place \
+                                of `{}`", lifetime_i.lifetime.name.name()))
+                            .emit();
+                    }
+                    hir::LifetimeName::Implicit |
+                    hir::LifetimeName::Name(_) => {
+                        self.resolve_lifetime_ref(bound);
+                    }
                 }
             }
         }
@@ -1472,9 +1492,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
     {
         for &(label, label_span) in &self.labels_in_fn {
             // FIXME (#24278): non-hygienic comparison
-            if lifetime.name == label {
+            if lifetime.name.name() == label {
                 signal_shadowing_problem(self.sess,
-                                         lifetime.name,
+                                         label,
                                          original_label(label_span),
                                          shadower_lifetime(&lifetime));
                 return;
@@ -1501,7 +1521,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
                         signal_shadowing_problem(
                             self.sess,
-                            lifetime.name,
+                            lifetime.name.name(),
                             original_lifetime(self.hir_map.span(node_id)),
                             shadower_lifetime(&lifetime));
                         return;
@@ -1617,7 +1637,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     return;
 
     struct ConstrainedCollector {
-        regions: FxHashSet<ast::Name>,
+        regions: FxHashSet<hir::LifetimeName>,
     }
 
     impl<'v> Visitor<'v> for ConstrainedCollector {
@@ -1657,7 +1677,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     }
 
     struct AllCollector {
-        regions: FxHashSet<ast::Name>,
+        regions: FxHashSet<hir::LifetimeName>,
         impl_trait: bool
     }
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d43504b77ba..ba221ef6ae1 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -18,6 +18,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
 use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
 use rustc_data_structures::control_flow_graph::ControlFlowGraph;
+use rustc_serialize as serialize;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use ty::subst::{Subst, Substs};
@@ -33,7 +34,7 @@ use std::fmt::{self, Debug, Formatter, Write};
 use std::{iter, u32};
 use std::ops::{Index, IndexMut};
 use std::vec::IntoIter;
-use syntax::ast::Name;
+use syntax::ast::{self, Name};
 use syntax_pos::Span;
 
 mod cache;
@@ -96,6 +97,10 @@ pub struct Mir<'tcx> {
     /// and used (eventually) for debuginfo. Indexed by a `VisibilityScope`.
     pub visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
 
+    /// Crate-local information for each visibility scope, that can't (and
+    /// needn't) be tracked across crates.
+    pub visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope, VisibilityScopeInfo>>,
+
     /// Rvalues promoted from this function, such as borrows of constants.
     /// Each of them is the Mir of a constant with the fn's type parameters
     /// in scope, but a separate set of locals.
@@ -151,6 +156,8 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0);
 impl<'tcx> Mir<'tcx> {
     pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
                visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
+               visibility_scope_info: ClearOnDecode<IndexVec<VisibilityScope,
+                                                             VisibilityScopeInfo>>,
                promoted: IndexVec<Promoted, Mir<'tcx>>,
                return_ty: Ty<'tcx>,
                yield_ty: Option<Ty<'tcx>>,
@@ -167,6 +174,7 @@ impl<'tcx> Mir<'tcx> {
         Mir {
             basic_blocks,
             visibility_scopes,
+            visibility_scope_info,
             promoted,
             return_ty,
             yield_ty,
@@ -278,9 +286,29 @@ impl<'tcx> Mir<'tcx> {
     }
 }
 
+#[derive(Clone, Debug)]
+pub struct VisibilityScopeInfo {
+    /// A NodeId with lint levels equivalent to this scope's lint levels.
+    pub lint_root: ast::NodeId,
+    /// The unsafe block that contains this node.
+    pub safety: Safety,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum Safety {
+    Safe,
+    /// Unsafe because of a PushUnsafeBlock
+    BuiltinUnsafe,
+    /// Unsafe because of an unsafe fn
+    FnUnsafe,
+    /// Unsafe because of an `unsafe` block
+    ExplicitUnsafe(ast::NodeId)
+}
+
 impl_stable_hash_for!(struct Mir<'tcx> {
     basic_blocks,
     visibility_scopes,
+    visibility_scope_info,
     promoted,
     return_ty,
     yield_ty,
@@ -310,10 +338,28 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
     }
 }
 
+#[derive(Clone, Debug)]
+pub enum ClearOnDecode<T> {
+    Clear,
+    Set(T)
+}
+
+impl<T> serialize::Encodable for ClearOnDecode<T> {
+    fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        serialize::Encodable::encode(&(), s)
+    }
+}
+
+impl<T> serialize::Decodable for ClearOnDecode<T> {
+    fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
+        serialize::Decodable::decode(d).map(|()| ClearOnDecode::Clear)
+    }
+}
+
 /// Grouped information about the source code origin of a MIR entity.
 /// Intended to be inspected by diagnostics and debuginfo.
 /// Most passes can work with it as a whole, within a single function.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct SourceInfo {
     /// Source span for the AST pertaining to this MIR entity.
     pub span: Span,
@@ -414,7 +460,7 @@ pub struct LocalDecl<'tcx> {
     /// True if this is an internal local
     ///
     /// These locals are not based on types in the source code and are only used
-    /// for drop flags at the moment.
+    /// for a few desugarings at the moment.
     ///
     /// The generator transformation will sanity check the locals which are live
     /// across a suspension point against the type components of the generator
@@ -422,6 +468,9 @@ pub struct LocalDecl<'tcx> {
     /// flag drop flags to avoid triggering this check as they are introduced
     /// after typeck.
     ///
+    /// Unsafety checking will also ignore dereferences of these locals,
+    /// so they can be used for raw pointers only used in a desugaring.
+    ///
     /// This should be sound because the drop flags are fully algebraic, and
     /// therefore don't affect the OIBIT or outlives properties of the
     /// generator.
@@ -438,6 +487,12 @@ pub struct LocalDecl<'tcx> {
 
     /// Source info of the local.
     pub source_info: SourceInfo,
+
+    /// The *lexical* visibility scope the local is defined
+    /// in. If the local was defined in a let-statement, this
+    /// is *within* the let-statement, rather than outside
+    /// of it.
+    pub lexical_scope: VisibilityScope,
 }
 
 impl<'tcx> LocalDecl<'tcx> {
@@ -452,6 +507,7 @@ impl<'tcx> LocalDecl<'tcx> {
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
+            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: false,
             is_user_variable: false
         }
@@ -468,6 +524,7 @@ impl<'tcx> LocalDecl<'tcx> {
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
+            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: true,
             is_user_variable: false
         }
@@ -485,6 +542,7 @@ impl<'tcx> LocalDecl<'tcx> {
                 span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
+            lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
             internal: false,
             name: None,     // FIXME maybe we do want some name here?
             is_user_variable: false
@@ -1592,6 +1650,13 @@ impl Location {
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct UnsafetyViolation {
+    pub source_info: SourceInfo,
+    pub description: &'static str,
+    pub lint_node_id: Option<ast::NodeId>,
+}
+
 /// The layout of generator state
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct GeneratorLayout<'tcx> {
@@ -1607,6 +1672,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
         Mir {
             basic_blocks: self.basic_blocks.fold_with(folder),
             visibility_scopes: self.visibility_scopes.clone(),
+            visibility_scope_info: self.visibility_scope_info.clone(),
             promoted: self.promoted.fold_with(folder),
             return_ty: self.return_ty.fold_with(folder),
             yield_ty: self.yield_ty.fold_with(folder),
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 37c97ad3dad..63652980f9b 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -690,11 +690,13 @@ macro_rules! make_mir_visitor {
                     name: _,
                     ref $($mutability)* source_info,
                     internal: _,
+                    ref $($mutability)* lexical_scope,
                     is_user_variable: _,
                 } = *local_decl;
 
                 self.visit_ty(ty, Lookup::Src(*source_info));
                 self.visit_source_info(source_info);
+                self.visit_visibility_scope(lexical_scope);
             }
 
             fn super_visibility_scope(&mut self,
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 1d490c8f27d..153d8c3a152 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -350,6 +350,9 @@ top_level_options!(
         // is currently just a hack and will be removed eventually, so please
         // try to not rely on this too much.
         actually_rustdoc: bool [TRACKED],
+
+        // Number of object files/codegen units to produce on the backend
+        codegen_units: usize [UNTRACKED],
     }
 );
 
@@ -512,6 +515,7 @@ pub fn basic_options() -> Options {
         unstable_features: UnstableFeatures::Disallow,
         debug_assertions: true,
         actually_rustdoc: false,
+        codegen_units: 1,
     }
 }
 
@@ -529,11 +533,6 @@ impl Options {
             (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
     }
 
-    pub fn single_codegen_unit(&self) -> bool {
-        self.incremental.is_none() ||
-        self.cg.codegen_units == 1
-    }
-
     pub fn file_path_mapping(&self) -> FilePathMapping {
         FilePathMapping::new(
             self.debugging_opts.remap_path_prefix_from.iter().zip(
@@ -791,7 +790,7 @@ macro_rules! options {
         fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
             match v {
                 Some(s) => { *slot = s.parse().ok(); slot.is_some() }
-                None => { *slot = None; true }
+                None => { *slot = None; false }
             }
         }
 
@@ -924,7 +923,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
          "metadata to mangle symbol names with"),
     extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
          "extra data to put in each output filename"),
-    codegen_units: usize = (1, parse_uint, [UNTRACKED],
+    codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
         "divide crate into N units to optimize in parallel"),
     remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED],
         "print remarks for these optimization passes (space separated, or \"all\")"),
@@ -1021,7 +1020,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "attempt to recover from parse errors (experimental)"),
     incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
           "enable incremental compilation (experimental)"),
-    incremental_cc: bool = (true, parse_bool, [UNTRACKED],
+    incremental_cc: bool = (false, parse_bool, [UNTRACKED],
           "enable cross-crate incremental compilation (even more experimental)"),
     incremental_info: bool = (false, parse_bool, [UNTRACKED],
         "print high-level information about incremental reuse (or the lack thereof)"),
@@ -1373,20 +1372,20 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                                  always = always colorize output;
                                  never  = never colorize output", "auto|always|never"),
 
-        opt::flagopt("", "pretty",
-                     "Pretty-print the input instead of compiling;
-                      valid types are: `normal` (un-annotated source),
-                      `expanded` (crates expanded), or
-                      `expanded,identified` (fully parenthesized, AST nodes with IDs).",
-                     "TYPE"),
-        opt::flagopt("", "unpretty",
-                     "Present the input source, unstable (and less-pretty) variants;
-                      valid types are any of the types for `--pretty`, as well as:
-                      `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
-                      `everybody_loops` (all function bodies replaced with `loop {}`),
-                      `hir` (the HIR), `hir,identified`, or
-                      `hir,typed` (HIR with types for each node).",
-                     "TYPE"),
+        opt::opt("", "pretty",
+                 "Pretty-print the input instead of compiling;
+                  valid types are: `normal` (un-annotated source),
+                  `expanded` (crates expanded), or
+                  `expanded,identified` (fully parenthesized, AST nodes with IDs).",
+                 "TYPE"),
+        opt::opt("", "unpretty",
+                 "Present the input source, unstable (and less-pretty) variants;
+                  valid types are any of the types for `--pretty`, as well as:
+                  `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+                  `everybody_loops` (all function bodies replaced with `loop {}`),
+                  `hir` (the HIR), `hir,identified`, or
+                  `hir,typed` (HIR with types for each node).",
+                 "TYPE"),
     ]);
     opts
 }
@@ -1521,27 +1520,35 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     }
 
     let mut cg = build_codegen_options(matches, error_format);
+    let mut codegen_units = cg.codegen_units;
 
     // Issue #30063: if user requests llvm-related output to one
     // particular path, disable codegen-units.
-    if matches.opt_present("o") && cg.codegen_units != 1 {
-        let incompatible: Vec<_> = output_types.iter()
-            .map(|ot_path| ot_path.0)
-            .filter(|ot| {
-                !ot.is_compatible_with_codegen_units_and_single_output_file()
-            }).collect();
-        if !incompatible.is_empty() {
-            for ot in &incompatible {
-                early_warn(error_format, &format!("--emit={} with -o incompatible with \
-                                                 -C codegen-units=N for N > 1",
-                                                ot.shorthand()));
+    let incompatible: Vec<_> = output_types.iter()
+        .map(|ot_path| ot_path.0)
+        .filter(|ot| {
+            !ot.is_compatible_with_codegen_units_and_single_output_file()
+        })
+        .map(|ot| ot.shorthand())
+        .collect();
+    if !incompatible.is_empty() {
+        match codegen_units {
+            Some(n) if n > 1 => {
+                if matches.opt_present("o") {
+                    for ot in &incompatible {
+                        early_warn(error_format, &format!("--emit={} with -o incompatible with \
+                                                         -C codegen-units=N for N > 1",
+                                                        ot));
+                    }
+                    early_warn(error_format, "resetting to default -C codegen-units=1");
+                    codegen_units = Some(1);
+                }
             }
-            early_warn(error_format, "resetting to default -C codegen-units=1");
-            cg.codegen_units = 1;
+            _ => codegen_units = Some(1),
         }
     }
 
-    if cg.codegen_units < 1 {
+    if codegen_units == Some(0) {
         early_error(error_format, "Value for codegen units must be a positive nonzero integer");
     }
 
@@ -1550,12 +1557,17 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     // case, but it would be confusing to have the validity of
     // `-Z lto -C codegen-units=2` depend on details of the crate being
     // compiled, so we complain regardless.
-    if cg.lto && cg.codegen_units > 1 {
-        // This case is impossible to handle because LTO expects to be able
-        // to combine the entire crate and all its dependencies into a
-        // single compilation unit, but each codegen unit is in a separate
-        // LLVM context, so they can't easily be combined.
-        early_error(error_format, "can't perform LTO when using multiple codegen units");
+    if cg.lto {
+        if let Some(n) = codegen_units {
+            if n > 1 {
+                // This case is impossible to handle because LTO expects to be able
+                // to combine the entire crate and all its dependencies into a
+                // single compilation unit, but each codegen unit is in a separate
+                // LLVM context, so they can't easily be combined.
+                early_error(error_format, "can't perform LTO when using multiple codegen units");
+            }
+        }
+        codegen_units = Some(1);
     }
 
     if cg.lto && debugging_opts.incremental.is_some() {
@@ -1720,6 +1732,34 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
 
     let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m));
 
+    let codegen_units = codegen_units.unwrap_or_else(|| {
+        match opt_level {
+            // If we're compiling at `-O0` then default to 32 codegen units.
+            // The number here shouldn't matter too too much as debug mode
+            // builds don't rely on performance at all, meaning that lost
+            // opportunities for inlining through multiple codegen units is
+            // a non-issue.
+            //
+            // Note that the high number here doesn't mean that we'll be
+            // spawning a large number of threads in parallel. The backend
+            // of rustc contains global rate limiting through the
+            // `jobserver` crate so we'll never overload the system with too
+            // much work, but rather we'll only be optimizing when we're
+            // otherwise cooperating with other instances of rustc.
+            //
+            // Rather the high number here means that we should be able to
+            // keep a lot of idle cpus busy. By ensuring that no codegen
+            // unit takes *too* long to build we'll be guaranteed that all
+            // cpus will finish pretty closely to one another and we should
+            // make relatively optimal use of system resources
+            OptLevel::No => 32,
+
+            // All other optimization levels default use one codegen unit,
+            // the historical default in Rust for a Long Time.
+            _ => 1,
+        }
+    });
+
     (Options {
         crate_types,
         optimize: opt_level,
@@ -1744,6 +1784,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         unstable_features: UnstableFeatures::from_environment(),
         debug_assertions,
         actually_rustdoc: false,
+        codegen_units,
     },
     cfg)
 }
@@ -2447,7 +2488,7 @@ mod tests {
         opts.cg.extra_filename = String::from("extra-filename");
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
-        opts.cg.codegen_units = 42;
+        opts.cg.codegen_units = Some(42);
         assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
         opts.cg.remark = super::SomePasses(vec![String::from("pass1"),
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 96f46b270a1..e87443619ec 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -411,7 +411,8 @@ impl Session {
     }
     pub fn emit_end_regions(&self) -> bool {
         self.opts.debugging_opts.emit_end_regions ||
-            (self.opts.debugging_opts.mir_emit_validate > 0)
+            (self.opts.debugging_opts.mir_emit_validate > 0) ||
+            self.opts.debugging_opts.borrowck_mir
     }
     pub fn lto(&self) -> bool {
         self.opts.cg.lto
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b491baadd7c..c7c8141f4f7 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -37,7 +37,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
 use std::fmt;
 use syntax::ast;
 use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
-use ty::error::{ExpectedFound, TypeError};
+use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::Subst;
@@ -711,7 +711,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 }
             }
 
-            OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
+            OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, _) => {
                 let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
                 let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
                 if actual_trait_ref.self_ty().references_error() {
@@ -722,48 +722,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     self.tcx.hir.span_if_local(did)
                 });
 
-                if let &TypeError::TupleSize(ref expected_found) = e {
-                    // Expected `|x| { }`, found `|x, y| { }`
-                    self.report_arg_count_mismatch(span,
-                                                   found_span,
-                                                   expected_found.expected,
-                                                   expected_found.found,
-                                                   expected_trait_ty.is_closure())
-                } else if let &TypeError::Sorts(ref expected_found) = e {
-                    let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty {
-                        tys.len()
-                    } else {
-                        1
+                let self_ty_count =
+                    match expected_trait_ref.skip_binder().substs.type_at(1).sty {
+                        ty::TyTuple(ref tys, _) => tys.len(),
+                        _ => 1,
                     };
-                    let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
-                        tys.len()
-                    } else {
-                        1
+                let arg_ty_count =
+                    match actual_trait_ref.skip_binder().substs.type_at(1).sty {
+                        ty::TyTuple(ref tys, _) => tys.len(),
+                        _ => 1,
                     };
-
-                    if expected != found {
-                        // Expected `|| { }`, found `|x, y| { }`
-                        // Expected `fn(x) -> ()`, found `|| { }`
-                        self.report_arg_count_mismatch(span,
-                                                       found_span,
-                                                       expected,
-                                                       found,
-                                                       expected_trait_ty.is_closure())
-                    } else {
-                        self.report_type_argument_mismatch(span,
-                                                            found_span,
-                                                            expected_trait_ty,
-                                                            expected_trait_ref,
-                                                            actual_trait_ref,
-                                                            e)
-                    }
+                if self_ty_count == arg_ty_count {
+                    self.report_closure_arg_mismatch(span,
+                                                     found_span,
+                                                     expected_trait_ref,
+                                                     actual_trait_ref)
                 } else {
-                    self.report_type_argument_mismatch(span,
-                                                        found_span,
-                                                        expected_trait_ty,
-                                                        expected_trait_ref,
-                                                        actual_trait_ref,
-                                                        e)
+                    // Expected `|| { }`, found `|x, y| { }`
+                    // Expected `fn(x) -> ()`, found `|| { }`
+                    self.report_arg_count_mismatch(
+                        span,
+                        found_span,
+                        arg_ty_count,
+                        self_ty_count,
+                        expected_trait_ty.is_closure()
+                    )
                 }
             }
 
@@ -784,31 +767,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         err.emit();
     }
 
-    fn report_type_argument_mismatch(&self,
-                                      span: Span,
-                                      found_span: Option<Span>,
-                                      expected_ty: Ty<'tcx>,
-                                      expected_ref: ty::PolyTraitRef<'tcx>,
-                                      found_ref: ty::PolyTraitRef<'tcx>,
-                                      type_error: &TypeError<'tcx>)
-        -> DiagnosticBuilder<'tcx>
-    {
-        let mut err = struct_span_err!(self.tcx.sess, span, E0281,
-            "type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required",
-            expected_ty,
-            expected_ref,
-            found_ref);
-
-        err.span_label(span, format!("{}", type_error));
-
-        if let Some(sp) = found_span {
-            err.span_label(span, format!("requires `{}`", found_ref));
-            err.span_label(sp, format!("implements `{}`", expected_ref));
-        }
-
-        err
-    }
-
     fn report_arg_count_mismatch(&self,
                                  span: Span,
                                  found_span: Option<Span>,
@@ -837,6 +795,57 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
         err
     }
+
+    fn report_closure_arg_mismatch(&self,
+                           span: Span,
+                           found_span: Option<Span>,
+                           expected_ref: ty::PolyTraitRef<'tcx>,
+                           found: ty::PolyTraitRef<'tcx>)
+        -> DiagnosticBuilder<'tcx>
+    {
+        fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
+                                               trait_ref: &ty::TraitRef<'tcx>) -> String {
+            let inputs = trait_ref.substs.type_at(1);
+            let sig = if let ty::TyTuple(inputs, _) = inputs.sty {
+                tcx.mk_fn_sig(
+                    inputs.iter().map(|&x| x),
+                    tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::syntax::abi::Abi::Rust
+                )
+            } else {
+                tcx.mk_fn_sig(
+                    ::std::iter::once(inputs),
+                    tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::syntax::abi::Abi::Rust
+                )
+            };
+            format!("{}", ty::Binder(sig))
+        }
+
+        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let mut err = struct_span_err!(self.tcx.sess, span, E0631,
+                                       "type mismatch in {} arguments",
+                                       if argument_is_closure { "closure" } else { "function" });
+
+        let found_str = format!(
+            "expected signature of `{}`",
+            build_fn_sig_string(self.tcx, found.skip_binder())
+        );
+        err.span_label(span, found_str);
+
+        let found_span = found_span.unwrap_or(span);
+        let expected_str = format!(
+            "found signature of `{}`",
+            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+        );
+        err.span_label(found_span, expected_str);
+
+        err
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
diff --git a/src/librustc/traits/trans/mod.rs b/src/librustc/traits/trans/mod.rs
index 9c4a260b35d..947e7117c4e 100644
--- a/src/librustc/traits/trans/mod.rs
+++ b/src/librustc/traits/trans/mod.rs
@@ -19,7 +19,7 @@ use std::cell::RefCell;
 use std::marker::PhantomData;
 use syntax::ast;
 use syntax_pos::Span;
-use traits::{FulfillmentContext, Obligation, ObligationCause, Reveal, SelectionContext, Vtable};
+use traits::{FulfillmentContext, Obligation, ObligationCause, SelectionContext, Vtable};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::{Subst, Substs};
 use ty::fold::{TypeFoldable, TypeFolder};
@@ -31,24 +31,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// (necessarily) resolve all nested obligations on the impl. Note
     /// that type check should guarantee to us that all nested
     /// obligations *could be* resolved if we wanted to.
+    /// Assumes that this is run after the entire crate has been successfully type-checked.
     pub fn trans_fulfill_obligation(self,
                                     span: Span,
+                                    param_env: ty::ParamEnv<'tcx>,
                                     trait_ref: ty::PolyTraitRef<'tcx>)
                                     -> Vtable<'tcx, ()>
     {
         // Remove any references to regions; this helps improve caching.
         let trait_ref = self.erase_regions(&trait_ref);
 
-        self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
+        self.trans_trait_caches.trait_cache.memoize((param_env, trait_ref), || {
             debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
-                   trait_ref, trait_ref.def_id());
+                   (param_env, trait_ref), trait_ref.def_id());
 
             // Do the initial selection for the obligation. This yields the
             // shallow result we are looking for -- that is, what specific impl.
             self.infer_ctxt().enter(|infcx| {
                 let mut selcx = SelectionContext::new(&infcx);
 
-                let param_env = ty::ParamEnv::empty(Reveal::All);
                 let obligation_cause = ObligationCause::misc(span,
                                                              ast::DUMMY_NODE_ID);
                 let obligation = Obligation::new(obligation_cause,
@@ -167,7 +168,7 @@ pub struct TraitSelectionCache<'tcx> {
 }
 
 impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
-    type Key = ty::PolyTraitRef<'tcx>;
+    type Key = (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>);
     type Value = Vtable<'tcx, ()>;
     fn to_dep_kind() -> DepKind {
         DepKind::TraitSelect
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 4a309ee0eb0..315ba622ccf 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -11,6 +11,7 @@
 //! type context book-keeping
 
 use dep_graph::DepGraph;
+use dep_graph::{DepNode, DepConstructor};
 use errors::DiagnosticBuilder;
 use session::Session;
 use session::config::OutputFilenames;
@@ -50,8 +51,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
-                                           StableHasher, StableHasherResult};
-
+                                           StableHasher, StableHasherResult,
+                                           StableVec};
 use arena::{TypedArena, DroplessArena};
 use rustc_const_math::{ConstInt, ConstUsize};
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -314,7 +315,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(RustcEncodable, RustcDecodable, Debug)]
 pub struct TypeckTables<'tcx> {
     /// The HirId::owner all ItemLocalIds in this table are relative to.
     pub local_id_root: Option<DefId>,
@@ -828,7 +829,9 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
-    trait_map: FxHashMap<DefIndex, Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
+    trait_map: FxHashMap<DefIndex,
+                         Rc<FxHashMap<ItemLocalId,
+                                      Rc<StableVec<TraitCandidate>>>>>,
 
     /// Export map produced by name resolution.
     export_map: FxHashMap<DefId, Rc<Vec<Export>>>,
@@ -1081,15 +1084,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             None
         };
 
-        // FIXME(mw): Each of the Vecs in the trait_map should be brought into
-        // a deterministic order here. Otherwise we might end up with
-        // unnecessarily unstable incr. comp. hashes.
         let mut trait_map = FxHashMap();
         for (k, v) in resolutions.trait_map {
             let hir_id = hir.node_to_hir_id(k);
             let map = trait_map.entry(hir_id.owner)
                 .or_insert_with(|| Rc::new(FxHashMap()));
-            Rc::get_mut(map).unwrap().insert(hir_id.local_id, Rc::new(v));
+            Rc::get_mut(map).unwrap()
+                            .insert(hir_id.local_id,
+                                    Rc::new(StableVec::new(v)));
         }
         let mut defs = FxHashMap();
         for (k, v) in named_region_map.defs {
@@ -1235,6 +1237,35 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   self.hir.definitions(),
                                   self.cstore)
     }
+
+    // This method makes sure that we have a DepNode and a Fingerprint for
+    // every upstream crate. It needs to be called once right after the tcx is
+    // created.
+    // With full-fledged red/green, the method will probably become unnecessary
+    // as this will be done on-demand.
+    pub fn allocate_metadata_dep_nodes(self) {
+        // We cannot use the query versions of crates() and crate_hash(), since
+        // those would need the DepNodes that we are allocating here.
+        for cnum in self.cstore.crates_untracked() {
+            let dep_node = DepNode::new(self, DepConstructor::CrateMetadata(cnum));
+            let crate_hash = self.cstore.crate_hash_untracked(cnum);
+            self.dep_graph.with_task(dep_node,
+                                     self,
+                                     crate_hash,
+                                     |_, x| x // No transformation needed
+            );
+        }
+    }
+
+    // This method exercises the `in_scope_traits_map` query for all possible
+    // values so that we have their fingerprints available in the DepGraph.
+    // This is only required as long as we still use the old dependency tracking
+    // which needs to have the fingerprints of all input nodes beforehand.
+    pub fn precompute_in_scope_traits_hashes(self) {
+        for &def_index in self.trait_map.keys() {
+            self.in_scope_traits_map(def_index);
+        }
+    }
 }
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
@@ -2103,7 +2134,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         lint::struct_lint_level(self.sess, lint, level, src, None, msg)
     }
 
-    pub fn in_scope_traits(self, id: HirId) -> Option<Rc<Vec<TraitCandidate>>> {
+    pub fn in_scope_traits(self, id: HirId) -> Option<Rc<StableVec<TraitCandidate>>> {
         self.in_scope_traits_map(id.owner)
             .and_then(|map| map.get(&id.local_id).cloned())
     }
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 313a831f6b0..4bd2d5be6d7 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -42,6 +42,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::StableVec;
 use std::cell::{RefCell, Cell};
 
 use std::ops::Deref;
@@ -158,6 +159,10 @@ define_maps! { <'tcx>
     /// expression defining the closure.
     [] fn closure_kind: ClosureKind(DefId) -> ty::ClosureKind,
 
+    /// Unsafety violations for this def ID.
+    [] fn unsafety_violations: UnsafetyViolations(DefId)
+        -> Rc<[mir::UnsafetyViolation]>,
+
     /// The signature of functions and closures.
     [] fn fn_sig: FnSignature(DefId) -> ty::PolyFnSig<'tcx>,
 
@@ -259,7 +264,7 @@ define_maps! { <'tcx>
 
     [] fn specializes: specializes_node((DefId, DefId)) -> bool,
     [] fn in_scope_traits_map: InScopeTraits(DefIndex)
-        -> Option<Rc<FxHashMap<ItemLocalId, Rc<Vec<TraitCandidate>>>>>,
+        -> Option<Rc<FxHashMap<ItemLocalId, Rc<StableVec<TraitCandidate>>>>>,
     [] fn module_exports: ModuleExports(DefId) -> Option<Rc<Vec<Export>>>,
     [] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
 
diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs
index 87a9eef0de5..581f47dc13c 100644
--- a/src/librustc/ty/maps/plumbing.rs
+++ b/src/librustc/ty/maps/plumbing.rs
@@ -221,7 +221,7 @@ macro_rules! define_maps {
 
                 profq_msg!(tcx,
                     ProfileQueriesMsg::QueryBegin(
-                        span.clone(),
+                        span.data(),
                         QueryMsg::$name(profq_key!(tcx, key))
                     )
                 );
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 2c1b3e28ffb..da635ec80fc 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -675,6 +675,8 @@ pub struct TypeParameterDef {
     /// on generic parameter `T`, asserts data behind the parameter
     /// `T` won't be accessed during the parent type's `Drop` impl.
     pub pure_wrt_drop: bool,
+
+    pub synthetic: Option<hir::SyntheticTyParamKind>,
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 618a4ed331e..9e566d2b907 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -20,7 +20,7 @@ use std::path::Path;
 use std::time::{Duration, Instant};
 
 use std::sync::mpsc::{Sender};
-use syntax_pos::{Span};
+use syntax_pos::{SpanData};
 use ty::maps::{QueryMsg};
 use dep_graph::{DepNode};
 
@@ -61,7 +61,8 @@ pub enum ProfileQueriesMsg {
     /// end a task
     TaskEnd,
     /// begin a new query
-    QueryBegin(Span, QueryMsg),
+    /// can't use `Span` because queries are sent to other thread
+    QueryBegin(SpanData, QueryMsg),
     /// query is satisfied by using an already-known value for the given key
     CacheHit,
     /// query requires running a provider; providers may nest, permitting queries to nest.
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index cf7a29d2845..214973e3085 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -26,6 +26,7 @@ use std::fmt;
 use std::usize;
 
 use rustc_const_math::ConstInt;
+use rustc_data_structures::indexed_vec::Idx;
 use syntax::abi::Abi;
 use syntax::ast::CRATE_NODE_ID;
 use syntax::symbol::Symbol;
@@ -530,17 +531,17 @@ impl fmt::Display for ty::RegionKind {
                 write!(f, "{}", br)
             }
             ty::ReScope(scope) if identify_regions() => {
-                match scope {
-                    region::Scope::Node(id) =>
+                match scope.data() {
+                    region::ScopeData::Node(id) =>
                         write!(f, "'{}s", id.as_usize()),
-                    region::Scope::CallSite(id) =>
+                    region::ScopeData::CallSite(id) =>
                         write!(f, "'{}cs", id.as_usize()),
-                    region::Scope::Arguments(id) =>
+                    region::ScopeData::Arguments(id) =>
                         write!(f, "'{}as", id.as_usize()),
-                    region::Scope::Destruction(id) =>
+                    region::ScopeData::Destruction(id) =>
                         write!(f, "'{}ds", id.as_usize()),
-                    region::Scope::Remainder(BlockRemainder { block, first_statement_index }) =>
-                        write!(f, "'{}_{}rs", block.as_usize(), first_statement_index),
+                    region::ScopeData::Remainder(BlockRemainder { block, first_statement_index }) =>
+                        write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()),
                 }
             }
             ty::ReVar(region_vid) if identify_regions() => {
@@ -676,6 +677,12 @@ impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
     }
 }
 
+impl<'tcx> fmt::Display for ty::Binder<ty::FnSig<'tcx>> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
+    }
+}
+
 impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
diff --git a/src/librustc_back/target/aarch64_unknown_linux_musl.rs b/src/librustc_back/target/aarch64_unknown_linux_musl.rs
new file mode 100644
index 00000000000..1edac616366
--- /dev/null
+++ b/src/librustc_back/target/aarch64_unknown_linux_musl.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.
+
+use LinkerFlavor;
+use target::{Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_musl_base::opts();
+    base.max_atomic_width = Some(128);
+
+    // see #36994
+    base.exe_allocation_crate = None;
+
+    Ok(Target {
+        llvm_target: "aarch64-unknown-linux-musl".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_env: "musl".to_string(),
+        data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "linux".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            abi_blacklist: super::arm_base::abi_blacklist(),
+            .. base
+        },
+    })
+}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 301cf3f8c82..27a0855dc29 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -153,6 +153,7 @@ supported_targets! {
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
     ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
+    ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
     ("mips-unknown-linux-musl", mips_unknown_linux_musl),
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index 7331016c2d2..e8f9a672087 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -138,7 +138,7 @@ impl FromIterator<bool> for BitVector {
 /// A "bit matrix" is basically a matrix of booleans represented as
 /// one gigantic bitvector. In other words, it is as if you have
 /// `rows` bitvectors, each of length `columns`.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct BitMatrix {
     columns: usize,
     vector: Vec<u64>,
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index f6b23af2f73..9aba48c5bef 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -558,3 +558,37 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F, W>(
     entries.hash_stable(hcx, hasher);
 }
 
+
+/// A vector container that makes sure that its items are hashed in a stable
+/// order.
+pub struct StableVec<T>(Vec<T>);
+
+impl<T> StableVec<T> {
+    pub fn new(v: Vec<T>) -> Self {
+        StableVec(v)
+    }
+}
+
+impl<T> ::std::ops::Deref for StableVec<T> {
+    type Target = Vec<T>;
+
+    fn deref(&self) -> &Vec<T> {
+        &self.0
+    }
+}
+
+impl<T, HCX> HashStable<HCX> for StableVec<T>
+    where T: HashStable<HCX> + ToStableHashKey<HCX>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut HCX,
+                                          hasher: &mut StableHasher<W>) {
+        let StableVec(ref v) = *self;
+
+        let mut sorted: Vec<_> = v.iter()
+                                  .map(|x| x.to_stable_hash_key(hcx))
+                                  .collect();
+        sorted.sort_unstable();
+        sorted.hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index 46463944043..7cb386b0197 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -18,7 +18,7 @@ use std::hash::Hash;
 use std::mem;
 
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
     // List of elements. This is used to map from a T to a usize.
     elements: Vec<T>,
@@ -42,10 +42,10 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
     closure: RefCell<Option<BitMatrix>>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
 struct Index(usize);
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
 struct Edge {
     source: Index,
     target: Index,
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index d50d3deb673..57989f75cba 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![cfg_attr(not(feature="llvm"), allow(dead_code))]
-
 use rustc::dep_graph::DepGraph;
 use rustc::hir::{self, map as hir_map};
 use rustc::hir::lowering::lower_crate;
@@ -30,12 +28,12 @@ use rustc::traits;
 use rustc::util::common::{ErrorReported, time};
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
-use rustc_incremental::{self, IncrementalHashesMap};
+use rustc_incremental;
 use rustc_resolve::{MakeGlobMap, Resolver};
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
-use rustc_trans::back::write;
 use rustc_trans as trans;
+use rustc_trans_utils::trans_crate::TransCrate;
 use rustc_typeck as typeck;
 use rustc_privacy;
 use rustc_plugin::registry::Registry;
@@ -43,6 +41,7 @@ use rustc_plugin as plugin;
 use rustc_passes::{ast_validation, no_asm, loops, consts, static_recursion, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
+use ::DefaultTransCrate;
 
 use serialize::json;
 
@@ -76,7 +75,8 @@ pub fn compile_input(sess: &Session,
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
                      control: &CompileController) -> CompileResult {
-    use rustc_trans::back::write::OngoingCrateTranslation;
+    use rustc::session::config::CrateType;
+
     macro_rules! controller_entry_point {
         ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
             let state = &mut $make_state;
@@ -94,17 +94,16 @@ pub fn compile_input(sess: &Session,
     }
 
     if cfg!(not(feature="llvm")) {
-        use rustc::session::config::CrateType;
-        if !sess.opts.debugging_opts.no_trans && sess.opts.output_types.should_trans() {
-            sess.err("LLVM is not supported by this rustc. Please use -Z no-trans to compile")
-        }
-
-        if sess.opts.crate_types.iter().all(|&t|{
-            t != CrateType::CrateTypeRlib && t != CrateType::CrateTypeExecutable
-        }) && !sess.opts.crate_types.is_empty() {
-            sess.err(
-                "LLVM is not supported by this rustc, so non rlib libraries are not supported"
-            );
+        for cty in sess.opts.crate_types.iter() {
+            match *cty {
+                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
+                CrateType::CrateTypeExecutable => {},
+                _ => {
+                    sess.parse_sess.span_diagnostic.warn(
+                        &format!("LLVM unsupported, so output type {} is not supported", cty)
+                    );
+                },
+            }
         }
 
         sess.abort_if_errors();
@@ -117,7 +116,7 @@ pub fn compile_input(sess: &Session,
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (outputs, trans, dep_graph): (OutputFilenames, OngoingCrateTranslation, DepGraph) = {
+    let (outputs, trans, dep_graph) = {
         let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
@@ -175,7 +174,7 @@ pub fn compile_input(sess: &Session,
         // Construct the HIR map
         let hir_map = time(sess.time_passes(),
                            "indexing hir",
-                           || hir_map::map_crate(&mut hir_forest, &defs));
+                           || hir_map::map_crate(sess, cstore, &mut hir_forest, &defs));
 
         {
             let _ignore = hir_map.dep_graph.in_ignore();
@@ -218,7 +217,7 @@ pub fn compile_input(sess: &Session,
                                     &arenas,
                                     &crate_name,
                                     &outputs,
-                                    |tcx, analysis, incremental_hashes_map, rx, result| {
+                                    |tcx, analysis, rx, result| {
             {
                 // Eventually, we will want to track plugins.
                 let _ignore = tcx.dep_graph.in_ignore();
@@ -246,9 +245,7 @@ pub fn compile_input(sess: &Session,
                 tcx.print_debug_stats();
             }
 
-            let trans = phase_4_translate_to_llvm(tcx,
-                                                  incremental_hashes_map,
-                                                  rx);
+            let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx);
 
             if log_enabled!(::log::LogLevel::Info) {
                 println!("Post-trans");
@@ -266,44 +263,42 @@ pub fn compile_input(sess: &Session,
         })??
     };
 
-    if cfg!(not(feature="llvm")) {
-        let (_, _) = (outputs, trans);
-        sess.fatal("LLVM is not supported by this rustc");
+    if sess.opts.debugging_opts.print_type_sizes {
+        sess.code_stats.borrow().print_type_sizes();
     }
 
-    #[cfg(feature="llvm")]
-    {
-        if sess.opts.debugging_opts.print_type_sizes {
-            sess.code_stats.borrow().print_type_sizes();
-        }
-
-        let (phase5_result, trans) = phase_5_run_llvm_passes(sess, &dep_graph, trans);
+    let (phase5_result, trans) =
+        phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans);
 
-        controller_entry_point!(after_llvm,
-                                sess,
-                                CompileState::state_after_llvm(input, sess, outdir, output, &trans),
-                                phase5_result);
-        phase5_result?;
+    controller_entry_point!(after_llvm,
+                            sess,
+                            CompileState::state_after_llvm(input, sess, outdir, output, &trans),
+                            phase5_result);
+    phase5_result?;
 
-        phase_6_link_output(sess, &trans, &outputs);
-
-        // Now that we won't touch anything in the incremental compilation directory
-        // any more, we can finalize it (which involves renaming it)
-        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+    // Run the linker on any artifacts that resulted from the LLVM run.
+    // This should produce either a finished executable or library.
+    time(sess.time_passes(), "linking", || {
+        DefaultTransCrate::link_binary(sess, &trans, &outputs)
+    });
 
-        if sess.opts.debugging_opts.perf_stats {
-            sess.print_perf_stats();
-        }
+    // Now that we won't touch anything in the incremental compilation directory
+    // any more, we can finalize it (which involves renaming it)
+    #[cfg(feature="llvm")]
+    rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
 
-        controller_entry_point!(
-            compilation_done,
-            sess,
-            CompileState::state_when_compilation_done(input, sess, outdir, output),
-            Ok(())
-        );
+    if sess.opts.debugging_opts.perf_stats {
+        sess.print_perf_stats();
+    }
 
+    controller_entry_point!(
+        compilation_done,
+        sess,
+        CompileState::state_when_compilation_done(input, sess, outdir, output),
         Ok(())
-    }
+    );
+
+    Ok(())
 }
 
 fn keep_hygiene_data(sess: &Session) -> bool {
@@ -645,7 +640,16 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         &crate_name,
         &disambiguator.as_str(),
     );
-    let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
+
+    let dep_graph = if sess.opts.build_dep_graph() {
+        let prev_dep_graph = time(time_passes, "load prev dep-graph (new)", || {
+            rustc_incremental::load_dep_graph_new(sess)
+        });
+
+        DepGraph::new(prev_dep_graph)
+    } else {
+        DepGraph::new_disabled()
+    };
 
     time(time_passes, "recursion limit", || {
         middle::recursion_limit::update_limits(sess, &krate);
@@ -715,7 +719,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // item, much like we do for macro expansion. In other words, the hash reflects not just
     // its contents but the results of name resolution on those contents. Hopefully we'll push
     // this back at some point.
-    let _ignore = dep_graph.in_ignore();
     let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
     let resolver_arenas = Resolver::arenas();
     let mut resolver = Resolver::new(sess,
@@ -921,7 +924,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                -> Result<R, CompileIncomplete>
     where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
                             ty::CrateAnalysis,
-                            IncrementalHashesMap,
                             mpsc::Receiver<Box<Any + Send>>,
                             CompileResult) -> R
 {
@@ -965,7 +967,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     mir::provide(&mut local_providers);
     reachable::provide(&mut local_providers);
     rustc_privacy::provide(&mut local_providers);
-    trans::provide_local(&mut local_providers);
+    DefaultTransCrate::provide_local(&mut local_providers);
     typeck::provide(&mut local_providers);
     ty::provide(&mut local_providers);
     traits::provide(&mut local_providers);
@@ -977,7 +979,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     let mut extern_providers = ty::maps::Providers::default();
     cstore::provide(&mut extern_providers);
-    trans::provide_extern(&mut extern_providers);
+    DefaultTransCrate::provide_extern(&mut extern_providers);
     ty::provide_extern(&mut extern_providers);
     traits::provide_extern(&mut extern_providers);
     // FIXME(eddyb) get rid of this once we replace const_eval with miri.
@@ -1000,19 +1002,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // What we need to run borrowck etc.
 
     passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
-
-    // FIXME: ariel points SimplifyBranches should run after
-    // mir-borrowck; otherwise code within `if false { ... }` would
-    // not be checked.
-    passes.push_pass(MIR_VALIDATED,
-                     mir::transform::simplify_branches::SimplifyBranches::new("initial"));
     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.
 
-    // These next passes must be executed together
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
+    passes.push_pass(MIR_OPTIMIZED,
+                     mir::transform::simplify_branches::SimplifyBranches::new("initial"));
+
+    // These next passes must be executed together
     passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
@@ -1053,22 +1052,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                              tx,
                              output_filenames,
                              |tcx| {
-        let incremental_hashes_map =
-            time(time_passes,
-                 "compute_incremental_hashes_map",
-                 || rustc_incremental::compute_incremental_hashes_map(tcx));
-
         time(time_passes,
              "load_dep_graph",
-             || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
+             || rustc_incremental::load_dep_graph(tcx));
 
         time(time_passes,
              "stability checking",
              || stability::check_unstable_api_usage(tcx));
 
         // passes are timed inside typeck
-        try_with_f!(typeck::check_crate(tcx),
-                    (tcx, analysis, incremental_hashes_map, rx));
+        try_with_f!(typeck::check_crate(tcx), (tcx, analysis, rx));
 
         time(time_passes,
              "const checking",
@@ -1082,10 +1075,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              || middle::intrinsicck::check_crate(tcx));
 
         time(time_passes,
-             "effect checking",
-             || middle::effect::check_crate(tcx));
-
-        time(time_passes,
              "match checking",
              || check_match::check_crate(tcx));
 
@@ -1105,6 +1094,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "MIR borrow checking",
              || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id) });
 
+        time(time_passes,
+             "MIR effect checking",
+             || for def_id in tcx.body_owners() {
+                 mir::transform::check_unsafety::check_unsafety(tcx, def_id)
+             });
         // Avoid overwhelming user with errors if type checking failed.
         // I'm not sure how helpful this is, to be honest, but it avoids
         // a
@@ -1112,7 +1106,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         // lint warnings and so on -- kindck used to do this abort, but
         // kindck is gone now). -nmatsakis
         if sess.err_count() > 0 {
-            return Ok(f(tcx, analysis, incremental_hashes_map, rx, sess.compile_status()));
+            return Ok(f(tcx, analysis, rx, sess.compile_status()));
         }
 
         time(time_passes, "death checking", || middle::dead::check_crate(tcx));
@@ -1123,16 +1117,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
         time(time_passes, "lint checking", || lint::check_crate(tcx));
 
-        return Ok(f(tcx, analysis, incremental_hashes_map, rx, tcx.sess.compile_status()));
+        return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
     })
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                           incremental_hashes_map: IncrementalHashesMap,
+pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            rx: mpsc::Receiver<Box<Any + Send>>)
-                                           -> write::OngoingCrateTranslation {
+                                           -> <Trans as TransCrate>::OngoingCrateTranslation {
     let time_passes = tcx.sess.time_passes();
 
     time(time_passes,
@@ -1141,9 +1134,8 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let translation =
         time(time_passes, "translation", move || {
-            trans::trans_crate(tcx, incremental_hashes_map, rx)
+            Trans::trans_crate(tcx, rx)
         });
-
     if tcx.sess.profile_queries() {
         profile::dump("profile_queries".to_string())
     }
@@ -1153,15 +1145,14 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
 /// as a side effect.
-#[cfg(feature="llvm")]
-pub fn phase_5_run_llvm_passes(sess: &Session,
+pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session,
                                dep_graph: &DepGraph,
-                               trans: write::OngoingCrateTranslation)
-                               -> (CompileResult, trans::CrateTranslation) {
-    let trans = trans.join(sess, dep_graph);
+                               trans: <Trans as TransCrate>::OngoingCrateTranslation)
+                               -> (CompileResult, <Trans as TransCrate>::TranslatedCrate) {
+    let trans = Trans::join_trans(trans, sess, dep_graph);
 
     if sess.opts.debugging_opts.incremental_info {
-        write::dump_incremental_data(&trans);
+        Trans::dump_incremental_data(&trans);
     }
 
     time(sess.time_passes(),
@@ -1171,20 +1162,6 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
     (sess.compile_status(), trans)
 }
 
-/// Run the linker on any artifacts that resulted from the LLVM run.
-/// This should produce either a finished executable or library.
-#[cfg(feature="llvm")]
-pub fn phase_6_link_output(sess: &Session,
-                           trans: &trans::CrateTranslation,
-                           outputs: &OutputFilenames) {
-    time(sess.time_passes(), "linking", || {
-        ::rustc_trans::back::link::link_binary(sess,
-                                               trans,
-                                               outputs,
-                                               &trans.crate_name.as_str())
-    });
-}
-
 fn escape_dep_filename(filename: &str) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 044f4a5eaf5..6bdad0b212c 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -75,6 +75,7 @@ use rustc::middle::cstore::CrateStore;
 use rustc_metadata::locator;
 use rustc_metadata::cstore::CStore;
 use rustc::util::common::{time, ErrorReported};
+use rustc_trans_utils::trans_crate::TransCrate;
 
 use serialize::json::ToJson;
 
@@ -151,101 +152,31 @@ pub fn run<F>(run_compiler: F) -> isize
 }
 
 #[cfg(not(feature="llvm"))]
-pub use no_llvm_metadata_loader::NoLLvmMetadataLoader as MetadataLoader;
+pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as DefaultTransCrate;
 #[cfg(feature="llvm")]
-pub use rustc_trans::LlvmMetadataLoader as MetadataLoader;
-
-#[cfg(not(feature="llvm"))]
-mod no_llvm_metadata_loader {
-    extern crate ar;
-    extern crate owning_ref;
-
-    use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
-    use rustc_back::target::Target;
-    use std::io;
-    use std::fs::File;
-    use std::path::Path;
-
-    use self::ar::Archive;
-    use self::owning_ref::{OwningRef, ErasedBoxRef};
-
-    pub struct NoLLvmMetadataLoader;
-
-    impl MetadataLoaderTrait for NoLLvmMetadataLoader {
-        fn get_rlib_metadata(
-            &self,
-            _: &Target,
-            filename: &Path
-        ) -> Result<ErasedBoxRef<[u8]>, String> {
-            let file = File::open(filename).map_err(|e| {
-                format!("metadata file open err: {:?}", e)
-            })?;
-            let mut archive = Archive::new(file);
-
-            while let Some(entry_result) = archive.next_entry() {
-                let mut entry = entry_result.map_err(|e| {
-                    format!("metadata section read err: {:?}", e)
-                })?;
-                if entry.header().identifier() == "rust.metadata.bin" {
-                    let mut buf = Vec::new();
-                    io::copy(&mut entry, &mut buf).unwrap();
-                    let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
-                    return Ok(buf.map_owner_box().erase_owner());
-                }
-            }
-
-            Err("Couldnt find metadata section".to_string())
-        }
-
-        fn get_dylib_metadata(&self,
-                            _target: &Target,
-                            _filename: &Path)
-                            -> Result<ErasedBoxRef<[u8]>, String> {
-            panic!("Dylib metadata loading not supported without LLVM")
-        }
-    }
-}
+pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
 
 #[cfg(not(feature="llvm"))]
 mod rustc_trans {
     use syntax_pos::symbol::Symbol;
     use rustc::session::Session;
-    use rustc::session::config::{PrintRequest, OutputFilenames};
-    use rustc::ty::{TyCtxt, CrateAnalysis};
-    use rustc::ty::maps::Providers;
-    use rustc_incremental::IncrementalHashesMap;
-
-    use self::back::write::OngoingCrateTranslation;
+    use rustc::session::config::PrintRequest;
+    pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
+    pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
 
     pub fn init(_sess: &Session) {}
     pub fn enable_llvm_debug() {}
-    pub fn provide(_providers: &mut Providers) {}
     pub fn print_version() {}
     pub fn print_passes() {}
     pub fn print(_req: PrintRequest, _sess: &Session) {}
     pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
 
-    pub fn trans_crate<'a, 'tcx>(
-        _tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        _analysis: CrateAnalysis,
-        _incr_hashes_map: IncrementalHashesMap,
-        _output_filenames: &OutputFilenames
-    ) -> OngoingCrateTranslation {
-        OngoingCrateTranslation(())
-    }
-
-    pub struct CrateTranslation(());
-
     pub mod back {
         pub mod write {
-            pub struct OngoingCrateTranslation(pub (in ::rustc_trans) ());
-
             pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
             pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
         }
     }
-
-    __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
 }
 
 // Parse args and run the compiler. This is the primary entry point for rustc.
@@ -293,7 +224,7 @@ pub fn run_compiler<'a>(args: &[String],
         },
     };
 
-    let cstore = Rc::new(CStore::new(box ::MetadataLoader));
+    let cstore = Rc::new(CStore::new(DefaultTransCrate::metadata_loader()));
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
@@ -1331,6 +1262,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
+    #[cfg(feature="llvm")]
     all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index cd153b82077..2f665af8433 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -20,7 +20,6 @@ use {abort_on_err, driver};
 use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions};
 use rustc::cfg;
 use rustc::cfg::graphviz::LabelledCFG;
-use rustc::dep_graph::DepGraph;
 use rustc::middle::cstore::CrateStore;
 use rustc::session::Session;
 use rustc::session::config::{Input, OutputFilenames};
@@ -237,7 +236,7 @@ impl PpSourceMode {
                                                                  arenas,
                                                                  id,
                                                                  output_filenames,
-                                                                 |tcx, _, _, _, _| {
+                                                                 |tcx, _, _, _| {
                     let empty_tables = ty::TypeckTables::empty(None);
                     let annotation = TypedAnnotation {
                         tcx,
@@ -848,9 +847,6 @@ pub fn print_after_parsing(sess: &Session,
                            krate: &ast::Crate,
                            ppm: PpMode,
                            ofile: Option<&Path>) {
-    let dep_graph = DepGraph::new(false);
-    let _ignore = dep_graph.in_ignore();
-
     let (src, src_name) = get_source(input, sess);
 
     let mut rdr = &*src;
@@ -893,9 +889,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                 output_filenames: &OutputFilenames,
                                                 opt_uii: Option<UserIdentifiedItem>,
                                                 ofile: Option<&Path>) {
-    let dep_graph = DepGraph::new(false);
-    let _ignore = dep_graph.in_ignore();
-
     if ppm.needs_analysis() {
         print_with_analysis(sess,
                             cstore,
@@ -1036,7 +1029,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                      arenas,
                                                      crate_name,
                                                      output_filenames,
-                                                     |tcx, _, _, _, _| {
+                                                     |tcx, _, _, _| {
         match ppm {
             PpmMir | PpmMirCFG => {
                 if let Some(nodeid) = nodeid {
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
index f5079836c3c..280f3c8c796 100644
--- a/src/librustc_driver/profile/trace.rs
+++ b/src/librustc_driver/profile/trace.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use super::*;
-use syntax_pos::Span;
+use syntax_pos::SpanData;
 use rustc::ty::maps::QueryMsg;
 use std::fs::File;
 use std::time::{Duration, Instant};
@@ -18,7 +18,7 @@ use rustc::dep_graph::{DepNode};
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Query {
-    pub span: Span,
+    pub span: SpanData,
     pub msg: QueryMsg,
 }
 pub enum Effect {
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index daabf481e46..6de36820f0c 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -30,6 +30,7 @@ use rustc::hir::map as hir_map;
 use rustc::mir::transform::Passes;
 use rustc::session::{self, config};
 use rustc::session::config::{OutputFilenames, OutputTypes};
+use rustc_trans_utils::trans_crate::TransCrate;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -105,7 +106,7 @@ fn test_env<F>(source_string: &str,
     options.unstable_features = UnstableFeatures::Allow;
     let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
 
-    let cstore = Rc::new(CStore::new(box ::MetadataLoader));
+    let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader()));
     let sess = session::build_session_(options,
                                        None,
                                        diagnostic_handler,
@@ -133,7 +134,7 @@ fn test_env<F>(source_string: &str,
 
     let arena = DroplessArena::new();
     let arenas = ty::GlobalArenas::new();
-    let hir_map = hir_map::map_crate(&mut hir_forest, &defs);
+    let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
 
     // run just enough stuff to build a tcx:
     let named_region_map = resolve_lifetime::krate(&sess, &*cstore, &hir_map);
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
deleted file mode 100644
index 0329aa8d674..00000000000
--- a/src/librustc_incremental/calculate_svh/mod.rs
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// 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.
-
-//! Calculation of the (misnamed) "strict version hash" for crates and
-//! items. This hash is used to tell when the HIR changed in such a
-//! way that results from previous compilations may no longer be
-//! applicable and hence must be recomputed. It should probably be
-//! renamed to the ICH (incremental compilation hash).
-//!
-//! The hashes for all items are computed once at the beginning of
-//! compilation and stored into a map. In addition, a hash is computed
-//! of the **entire crate**.
-//!
-//! Storing the hashes in a map avoids the need to compute them twice
-//! (once when loading prior incremental results and once when
-//! saving), but it is also important for correctness: at least as of
-//! the time of this writing, the typeck passes rewrites entries in
-//! the dep-map in-place to accommodate UFCS resolutions. Since name
-//! resolution is part of the hash, the result is that hashes computed
-//! at the end of compilation would be different from those computed
-//! at the beginning.
-
-use std::cell::RefCell;
-use std::hash::Hash;
-use rustc::dep_graph::{DepNode, DepKind};
-use rustc::hir;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
-use rustc::hir::map::DefPathHash;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::ich::{Fingerprint, StableHashingContext};
-use rustc::ty::TyCtxt;
-use rustc::util::common::record_time;
-use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::accumulate_vec::AccumulateVec;
-
-pub type IchHasher = StableHasher<Fingerprint>;
-
-pub struct IncrementalHashesMap {
-    hashes: FxHashMap<DepNode, Fingerprint>,
-
-    // These are the metadata hashes for the current crate as they were stored
-    // during the last compilation session. They are only loaded if
-    // -Z query-dep-graph was specified and are needed for auto-tests using
-    // the #[rustc_metadata_dirty] and #[rustc_metadata_clean] attributes to
-    // check whether some metadata hash has changed in between two revisions.
-    pub prev_metadata_hashes: RefCell<FxHashMap<DefId, Fingerprint>>,
-}
-
-impl IncrementalHashesMap {
-    pub fn new() -> IncrementalHashesMap {
-        IncrementalHashesMap {
-            hashes: FxHashMap(),
-            prev_metadata_hashes: RefCell::new(FxHashMap()),
-        }
-    }
-
-    pub fn insert(&mut self, k: DepNode, v: Fingerprint) {
-        assert!(self.hashes.insert(k, v).is_none());
-    }
-
-    pub fn iter<'a>(&'a self)
-                    -> ::std::collections::hash_map::Iter<'a, DepNode, Fingerprint> {
-        self.hashes.iter()
-    }
-
-    pub fn len(&self) -> usize {
-        self.hashes.len()
-    }
-}
-
-impl<'a> ::std::ops::Index<&'a DepNode> for IncrementalHashesMap {
-    type Output = Fingerprint;
-
-    fn index(&self, index: &'a DepNode) -> &Fingerprint {
-        match self.hashes.get(index) {
-            Some(fingerprint) => fingerprint,
-            None => {
-                bug!("Could not find ICH for {:?}", index);
-            }
-        }
-    }
-}
-
-struct ComputeItemHashesVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    hcx: StableHashingContext<'tcx>,
-    hashes: IncrementalHashesMap,
-}
-
-impl<'a, 'tcx: 'a> ComputeItemHashesVisitor<'a, 'tcx> {
-    fn compute_and_store_ich_for_item_like<T>(&mut self,
-                                              def_index: DefIndex,
-                                              hash_bodies: bool,
-                                              item_like: T)
-        where T: HashStable<StableHashingContext<'tcx>>
-    {
-        if !hash_bodies && !self.tcx.sess.opts.build_dep_graph() {
-            // If we just need the hashes in order to compute the SVH, we don't
-            // need have two hashes per item. Just the one containing also the
-            // item's body is sufficient.
-            return
-        }
-
-        let def_path_hash = self.hcx.local_def_path_hash(def_index);
-
-        let mut hasher = IchHasher::new();
-        self.hcx.while_hashing_hir_bodies(hash_bodies, |hcx| {
-            item_like.hash_stable(hcx, &mut hasher);
-        });
-
-        let bytes_hashed = hasher.bytes_hashed();
-        let item_hash = hasher.finish();
-        let dep_node = if hash_bodies {
-            def_path_hash.to_dep_node(DepKind::HirBody)
-        } else {
-            def_path_hash.to_dep_node(DepKind::Hir)
-        };
-        debug!("calculate_def_hash: dep_node={:?} hash={:?}", dep_node, item_hash);
-        self.hashes.insert(dep_node, item_hash);
-
-        let bytes_hashed =
-            self.tcx.sess.perf_stats.incr_comp_bytes_hashed.get() + bytes_hashed;
-        self.tcx.sess.perf_stats.incr_comp_bytes_hashed.set(bytes_hashed);
-
-        if hash_bodies {
-            let in_scope_traits_map = self.tcx.in_scope_traits_map(def_index);
-            let mut hasher = IchHasher::new();
-            in_scope_traits_map.hash_stable(&mut self.hcx, &mut hasher);
-            let dep_node = def_path_hash.to_dep_node(DepKind::InScopeTraits);
-            self.hashes.insert(dep_node, hasher.finish());
-        }
-    }
-
-    fn compute_crate_hash(&mut self) {
-        let krate = self.tcx.hir.krate();
-
-        let mut crate_state = IchHasher::new();
-
-        let crate_disambiguator = self.tcx.sess.local_crate_disambiguator();
-        "crate_disambiguator".hash(&mut crate_state);
-        crate_disambiguator.as_str().len().hash(&mut crate_state);
-        crate_disambiguator.as_str().hash(&mut crate_state);
-
-        // add each item (in some deterministic order) to the overall
-        // crate hash.
-        {
-            let mut item_hashes: Vec<_> =
-                self.hashes.iter()
-                           .filter_map(|(&item_dep_node, &item_hash)| {
-                                // This `match` determines what kinds of nodes
-                                // go into the SVH:
-                                match item_dep_node.kind {
-                                    DepKind::InScopeTraits |
-                                    DepKind::Hir |
-                                    DepKind::HirBody => {
-                                        // We want to incoporate these into the
-                                        // SVH.
-                                    }
-                                    DepKind::AllLocalTraitImpls => {
-                                        // These are already covered by hashing
-                                        // the HIR.
-                                        return None
-                                    }
-                                    ref other => {
-                                        bug!("Found unexpected DepKind during \
-                                              SVH computation: {:?}",
-                                             other)
-                                    }
-                                }
-
-                                Some((item_dep_node, item_hash))
-                           })
-                           .collect();
-            item_hashes.sort_unstable(); // avoid artificial dependencies on item ordering
-            item_hashes.hash(&mut crate_state);
-        }
-
-        krate.attrs.hash_stable(&mut self.hcx, &mut crate_state);
-
-        let crate_hash = crate_state.finish();
-        self.hashes.insert(DepNode::new_no_params(DepKind::Krate), crate_hash);
-        debug!("calculate_crate_hash: crate_hash={:?}", crate_hash);
-    }
-
-    fn hash_crate_root_module(&mut self, krate: &'tcx hir::Crate) {
-        let hir::Crate {
-            ref module,
-            // Crate attributes are not copied over to the root `Mod`, so hash
-            // them explicitly here.
-            ref attrs,
-            span,
-
-            // These fields are handled separately:
-            exported_macros: _,
-            items: _,
-            trait_items: _,
-            impl_items: _,
-            bodies: _,
-            trait_impls: _,
-            trait_default_impl: _,
-            body_ids: _,
-        } = *krate;
-
-        self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
-                                                 false,
-                                                 (module, (span, attrs)));
-        self.compute_and_store_ich_for_item_like(CRATE_DEF_INDEX,
-                                                 true,
-                                                 (module, (span, attrs)));
-    }
-
-    fn compute_and_store_ich_for_trait_impls(&mut self, krate: &'tcx hir::Crate)
-    {
-        let tcx = self.tcx;
-
-        let mut impls: Vec<(DefPathHash, Fingerprint)> = krate
-            .trait_impls
-            .iter()
-            .map(|(&trait_id, impls)| {
-                let trait_id = tcx.def_path_hash(trait_id);
-                let mut impls: AccumulateVec<[_; 32]> = impls
-                    .iter()
-                    .map(|&node_id| {
-                        let def_id = tcx.hir.local_def_id(node_id);
-                        tcx.def_path_hash(def_id)
-                    })
-                    .collect();
-
-                impls.sort_unstable();
-                let mut hasher = StableHasher::new();
-                impls.hash_stable(&mut self.hcx, &mut hasher);
-                (trait_id, hasher.finish())
-            })
-            .collect();
-
-        impls.sort_unstable();
-
-        let mut default_impls: AccumulateVec<[_; 32]> = krate
-            .trait_default_impl
-            .iter()
-            .map(|(&trait_def_id, &impl_node_id)| {
-                let impl_def_id = tcx.hir.local_def_id(impl_node_id);
-                (tcx.def_path_hash(trait_def_id), tcx.def_path_hash(impl_def_id))
-            })
-            .collect();
-
-        default_impls.sort_unstable();
-
-        let mut hasher = StableHasher::new();
-        impls.hash_stable(&mut self.hcx, &mut hasher);
-
-        self.hashes.insert(DepNode::new_no_params(DepKind::AllLocalTraitImpls),
-                           hasher.finish());
-    }
-}
-
-impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for ComputeItemHashesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
-        let def_index = self.tcx.hir.local_def_id(item.id).index;
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 false,
-                                                 item);
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 true,
-                                                 item);
-    }
-
-    fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        let def_index = self.tcx.hir.local_def_id(item.id).index;
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 false,
-                                                 item);
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 true,
-                                                 item);
-    }
-
-    fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
-        let def_index = self.tcx.hir.local_def_id(item.id).index;
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 false,
-                                                 item);
-        self.compute_and_store_ich_for_item_like(def_index,
-                                                 true,
-                                                 item);
-    }
-}
-
-
-
-pub fn compute_incremental_hashes_map<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                                    -> IncrementalHashesMap {
-    let _ignore = tcx.dep_graph.in_ignore();
-    let krate = tcx.hir.krate();
-
-    let mut visitor = ComputeItemHashesVisitor {
-        tcx,
-        hcx: tcx.create_stable_hashing_context(),
-        hashes: IncrementalHashesMap::new(),
-    };
-
-    record_time(&tcx.sess.perf_stats.incr_comp_hashes_time, || {
-        visitor.hash_crate_root_module(krate);
-        krate.visit_all_item_likes(&mut visitor);
-
-        for macro_def in krate.exported_macros.iter() {
-            let def_index = tcx.hir.local_def_id(macro_def.id).index;
-            visitor.compute_and_store_ich_for_item_like(def_index,
-                                                        false,
-                                                        macro_def);
-            visitor.compute_and_store_ich_for_item_like(def_index,
-                                                        true,
-                                                        macro_def);
-        }
-
-        visitor.compute_and_store_ich_for_trait_impls(krate);
-    });
-
-    tcx.sess.perf_stats.incr_comp_hashes_count.set(visitor.hashes.len() as u64);
-
-    record_time(&tcx.sess.perf_stats.svh_time, || visitor.compute_crate_hash());
-    visitor.hashes
-}
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 3c1e02f8a5a..0fba6d8e9c6 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -28,14 +28,11 @@ extern crate syntax;
 extern crate syntax_pos;
 
 mod assert_dep_graph;
-mod calculate_svh;
 mod persist;
 
 pub use assert_dep_graph::assert_dep_graph;
-pub use calculate_svh::compute_incremental_hashes_map;
-pub use calculate_svh::IncrementalHashesMap;
-pub use calculate_svh::IchHasher;
 pub use persist::load_dep_graph;
+pub use persist::load_dep_graph_new;
 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/data.rs b/src/librustc_incremental/persist/data.rs
index 06acfb5d778..9050702e3ca 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -70,14 +70,6 @@ impl SerializedDepGraph {
          RustcEncodable, RustcDecodable)]
 pub struct DepNodeIndex(pub u32);
 
-impl DepNodeIndex {
-    #[inline]
-    pub fn new(idx: usize) -> DepNodeIndex {
-        assert!(idx <= ::std::u32::MAX as usize);
-        DepNodeIndex(idx as u32)
-    }
-}
-
 impl Idx for DepNodeIndex {
     #[inline]
     fn new(idx: usize) -> Self {
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 126057fd043..a6d39a91863 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -8,18 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Debugging code to test the state of the dependency graph just
-//! after it is loaded from disk and just after it has been saved.
+//! Debugging code to test fingerprints computed for query results.
 //! For each node marked with `#[rustc_clean]` or `#[rustc_dirty]`,
-//! we will check that a suitable node for that item either appears
-//! or does not appear in the dep-graph, as appropriate:
+//! we will compare the fingerprint from the current and from the previous
+//! compilation session as appropriate:
 //!
 //! - `#[rustc_dirty(label="TypeckTables", cfg="rev2")]` if we are
-//!   in `#[cfg(rev2)]`, then there MUST NOT be a node
-//!   `DepNode::TypeckTables(X)` where `X` is the def-id of the
-//!   current node.
+//!   in `#[cfg(rev2)]`, then the fingerprints associated with
+//!   `DepNode::TypeckTables(X)` must be DIFFERENT (`X` is the def-id of the
+//!   current node).
 //! - `#[rustc_clean(label="TypeckTables", cfg="rev2")]` same as above,
-//!   except that the node MUST exist.
+//!   except that the fingerprints must be the SAME.
 //!
 //! Errors are reported if we are in the suitable configuration but
 //! the required condition is not met.
@@ -40,9 +39,7 @@
 //! previous revision to compare things to.
 //!
 
-use super::data::DepNodeIndex;
-use super::load::DirtyNodes;
-use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind};
+use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -51,41 +48,22 @@ use rustc::ich::{Fingerprint, ATTR_DIRTY, ATTR_CLEAN, ATTR_DIRTY_METADATA,
                  ATTR_CLEAN_METADATA};
 use syntax::ast::{self, Attribute, NestedMetaItem};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use rustc_data_structures::indexed_vec::IndexVec;
 use syntax_pos::Span;
 use rustc::ty::TyCtxt;
 
 const LABEL: &'static str = "label";
 const CFG: &'static str = "cfg";
 
-pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               nodes: &IndexVec<DepNodeIndex, DepNode>,
-                                               dirty_inputs: &DirtyNodes) {
+pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     // can't add `#[rustc_dirty]` etc without opting in to this feature
     if !tcx.sess.features.borrow().rustc_attrs {
         return;
     }
 
     let _ignore = tcx.dep_graph.in_ignore();
-    let dirty_inputs: FxHashSet<DepNode> =
-        dirty_inputs.keys()
-                    .filter_map(|dep_node_index| {
-                        let dep_node = nodes[*dep_node_index];
-                        if dep_node.extract_def_id(tcx).is_some() {
-                            Some(dep_node)
-                        } else {
-                            None
-                        }
-                    })
-                    .collect();
-
-    let query = tcx.dep_graph.query();
-    debug!("query-nodes: {:?}", query.nodes());
     let krate = tcx.hir.krate();
     let mut dirty_clean_visitor = DirtyCleanVisitor {
         tcx,
-        query: &query,
-        dirty_inputs,
         checked_attrs: FxHashSet(),
     };
     krate.visit_all_item_likes(&mut dirty_clean_visitor);
@@ -105,8 +83,6 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    query: &'a DepGraphQuery,
-    dirty_inputs: FxHashSet<DepNode>,
     checked_attrs: FxHashSet<ast::AttrId>,
 }
 
@@ -143,59 +119,28 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
     fn assert_dirty(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_dirty({:?})", dep_node);
 
-        match dep_node.kind {
-            DepKind::Krate |
-            DepKind::Hir |
-            DepKind::HirBody => {
-                // HIR nodes are inputs, so if we are asserting that the HIR node is
-                // dirty, we check the dirty input set.
-                if !self.dirty_inputs.contains(&dep_node) {
-                    let dep_node_str = self.dep_node_str(&dep_node);
-                    self.tcx.sess.span_err(
-                        item_span,
-                        &format!("`{}` not found in dirty set, but should be dirty",
-                                 dep_node_str));
-                }
-            }
-            _ => {
-                // Other kinds of nodes would be targets, so check if
-                // the dep-graph contains the node.
-                if self.query.contains_node(&dep_node) {
-                    let dep_node_str = self.dep_node_str(&dep_node);
-                    self.tcx.sess.span_err(
-                        item_span,
-                        &format!("`{}` found in dep graph, but should be dirty", dep_node_str));
-                }
-            }
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
+
+        if current_fingerprint == prev_fingerprint {
+            let dep_node_str = self.dep_node_str(&dep_node);
+            self.tcx.sess.span_err(
+                item_span,
+                &format!("`{}` should be dirty but is not", dep_node_str));
         }
     }
 
     fn assert_clean(&self, item_span: Span, dep_node: DepNode) {
         debug!("assert_clean({:?})", dep_node);
 
-        match dep_node.kind {
-            DepKind::Krate |
-            DepKind::Hir |
-            DepKind::HirBody => {
-                // For HIR nodes, check the inputs.
-                if self.dirty_inputs.contains(&dep_node) {
-                    let dep_node_str = self.dep_node_str(&dep_node);
-                    self.tcx.sess.span_err(
-                        item_span,
-                        &format!("`{}` found in dirty-node set, but should be clean",
-                                 dep_node_str));
-                }
-            }
-            _ => {
-                // Otherwise, check if the dep-node exists.
-                if !self.query.contains_node(&dep_node) {
-                    let dep_node_str = self.dep_node_str(&dep_node);
-                    self.tcx.sess.span_err(
-                        item_span,
-                        &format!("`{}` not found in dep graph, but should be clean",
-                                 dep_node_str));
-                }
-            }
+        let current_fingerprint = self.tcx.dep_graph.fingerprint_of(&dep_node);
+        let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node);
+
+        if current_fingerprint != prev_fingerprint {
+            let dep_node_str = self.dep_node_str(&dep_node);
+            self.tcx.sess.span_err(
+                item_span,
+                &format!("`{}` should be clean but is not", dep_node_str));
         }
     }
 
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index f3f35a50fe0..592b8f1a9eb 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -114,15 +114,12 @@
 //! unsupported file system and emit a warning in that case. This is not yet
 //! implemented.
 
-use rustc::hir::def_id::CrateNum;
 use rustc::hir::svh::Svh;
 use rustc::session::Session;
-use rustc::ty::TyCtxt;
 use rustc::util::fs as fs_util;
 use rustc_data_structures::{flock, base_n};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
-use std::ffi::OsString;
 use std::fs as std_fs;
 use std::io;
 use std::mem;
@@ -132,6 +129,7 @@ use std::__rand::{thread_rng, Rng};
 
 const LOCK_FILE_EXT: &'static str = ".lock";
 const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
+const DEP_GRAPH_NEW_FILENAME: &'static str = "dep-graph-new.bin";
 const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
 const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
 
@@ -145,6 +143,10 @@ pub fn dep_graph_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
 }
 
+pub fn dep_graph_path_new(sess: &Session) -> PathBuf {
+    in_incr_comp_dir_sess(sess, DEP_GRAPH_NEW_FILENAME)
+}
+
 pub fn work_products_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME)
 }
@@ -153,10 +155,6 @@ pub fn metadata_hash_export_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, METADATA_HASHES_FILENAME)
 }
 
-pub fn metadata_hash_import_path(import_session_dir: &Path) -> PathBuf {
-    import_session_dir.join(METADATA_HASHES_FILENAME)
-}
-
 pub fn lock_file_path(session_dir: &Path) -> PathBuf {
     let crate_dir = session_dir.parent().unwrap();
 
@@ -616,70 +614,6 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path_tcx(tcx: TyCtxt, cnum: CrateNum) -> PathBuf {
-    crate_path(tcx.sess, &tcx.crate_name(cnum).as_str(), &tcx.crate_disambiguator(cnum).as_str())
-}
-
-/// Finds the session directory containing the correct metadata hashes file for
-/// the given crate. In order to do that it has to compute the crate directory
-/// of the given crate, and in there, look for the session directory with the
-/// correct SVH in it.
-/// Note that we have to match on the exact SVH here, not just the
-/// crate's (name, disambiguator) pair. The metadata hashes are only valid for
-/// the exact version of the binary we are reading from now (i.e. the hashes
-/// are part of the dependency graph of a specific compilation session).
-pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option<PathBuf> {
-    let crate_directory = crate_path_tcx(tcx, cnum);
-
-    if !crate_directory.exists() {
-        return None
-    }
-
-    let dir_entries = match crate_directory.read_dir() {
-        Ok(dir_entries) => dir_entries,
-        Err(e) => {
-            tcx.sess
-               .err(&format!("incremental compilation: Could not read crate directory `{}`: {}",
-                             crate_directory.display(), e));
-            return None
-        }
-    };
-
-    let target_svh = tcx.crate_hash(cnum);
-    let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE);
-
-    let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| {
-        e.ok().map(|e| e.file_name().to_string_lossy().into_owned())
-    }));
-
-    sub_dir.map(|sub_dir_name| crate_directory.join(&sub_dir_name))
-}
-
-fn find_metadata_hashes_iter<'a, I>(target_svh: &str, iter: I) -> Option<OsString>
-    where I: Iterator<Item=String>
-{
-    for sub_dir_name in iter {
-        if !is_session_directory(&sub_dir_name) || !is_finalized(&sub_dir_name) {
-            // This is not a usable session directory
-            continue
-        }
-
-        let is_match = if let Some(last_dash_pos) = sub_dir_name.rfind("-") {
-            let candidate_svh = &sub_dir_name[last_dash_pos + 1 .. ];
-            target_svh == candidate_svh
-        } else {
-            // some kind of invalid directory name
-            continue
-        };
-
-        if is_match {
-            return Some(OsString::from(sub_dir_name))
-        }
-    }
-
-    None
-}
-
 fn crate_path(sess: &Session,
               crate_name: &str,
               crate_disambiguator: &str)
@@ -1019,52 +953,3 @@ fn test_find_source_directory_in_iter() {
              PathBuf::from("crate-dir/s-1234-0000-working")].into_iter(), &already_visited),
         None);
 }
-
-#[test]
-fn test_find_metadata_hashes_iter()
-{
-    assert_eq!(find_metadata_hashes_iter("testsvh2",
-        vec![
-            String::from("s-timestamp1-testsvh1"),
-            String::from("s-timestamp2-testsvh2"),
-            String::from("s-timestamp3-testsvh3"),
-        ].into_iter()),
-        Some(OsString::from("s-timestamp2-testsvh2"))
-    );
-
-    assert_eq!(find_metadata_hashes_iter("testsvh2",
-        vec![
-            String::from("s-timestamp1-testsvh1"),
-            String::from("s-timestamp2-testsvh2"),
-            String::from("invalid-name"),
-        ].into_iter()),
-        Some(OsString::from("s-timestamp2-testsvh2"))
-    );
-
-    assert_eq!(find_metadata_hashes_iter("testsvh2",
-        vec![
-            String::from("s-timestamp1-testsvh1"),
-            String::from("s-timestamp2-testsvh2-working"),
-            String::from("s-timestamp3-testsvh3"),
-        ].into_iter()),
-        None
-    );
-
-    assert_eq!(find_metadata_hashes_iter("testsvh1",
-        vec![
-            String::from("s-timestamp1-random1-working"),
-            String::from("s-timestamp2-random2-working"),
-            String::from("s-timestamp3-random3-working"),
-        ].into_iter()),
-        None
-    );
-
-    assert_eq!(find_metadata_hashes_iter("testsvh2",
-        vec![
-            String::from("timestamp1-testsvh2"),
-            String::from("timestamp2-testsvh2"),
-            String::from("timestamp3-testsvh2"),
-        ].into_iter()),
-        None
-    );
-}
diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs
deleted file mode 100644
index 8355f319139..00000000000
--- a/src/librustc_incremental/persist/hash.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::dep_graph::{DepNode, DepKind};
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::hir::svh::Svh;
-use rustc::ich::Fingerprint;
-use rustc::ty::TyCtxt;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::flock;
-use rustc_serialize::Decodable;
-use rustc_serialize::opaque::Decoder;
-
-use IncrementalHashesMap;
-use super::data::*;
-use super::fs::*;
-use super::file_format;
-
-use std::hash::Hash;
-use std::fmt::Debug;
-
-pub struct HashContext<'a, 'tcx: 'a> {
-    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    incremental_hashes_map: &'a IncrementalHashesMap,
-    metadata_hashes: FxHashMap<DefId, Fingerprint>,
-    crate_hashes: FxHashMap<CrateNum, Svh>,
-}
-
-impl<'a, 'tcx> HashContext<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               incremental_hashes_map: &'a IncrementalHashesMap)
-               -> Self {
-        HashContext {
-            tcx,
-            incremental_hashes_map,
-            metadata_hashes: FxHashMap(),
-            crate_hashes: FxHashMap(),
-        }
-    }
-
-    pub fn is_hashable(tcx: TyCtxt, dep_node: &DepNode) -> bool {
-        match dep_node.kind {
-            DepKind::Krate |
-            DepKind::Hir |
-            DepKind::InScopeTraits |
-            DepKind::HirBody =>
-                true,
-            DepKind::MetaData => {
-                let def_id = dep_node.extract_def_id(tcx).unwrap();
-                !def_id.is_local()
-            }
-            _ => false,
-        }
-    }
-
-    pub fn hash(&mut self, dep_node: &DepNode) -> Option<Fingerprint> {
-        match dep_node.kind {
-            DepKind::Krate => {
-                Some(self.incremental_hashes_map[dep_node])
-            }
-
-            // HIR nodes (which always come from our crate) are an input:
-            DepKind::InScopeTraits |
-            DepKind::Hir |
-            DepKind::HirBody => {
-                Some(self.incremental_hashes_map[dep_node])
-            }
-
-            // MetaData from other crates is an *input* to us.
-            // MetaData nodes from *our* crates are an *output*; we
-            // don't hash them, but we do compute a hash for them and
-            // save it for others to use.
-            DepKind::MetaData => {
-                let def_id = dep_node.extract_def_id(self.tcx).unwrap();
-                if !def_id.is_local() {
-                    Some(self.metadata_hash(def_id,
-                                        def_id.krate,
-                                        |this| &mut this.metadata_hashes))
-                } else {
-                    None
-                }
-            }
-
-            _ => {
-                // Other kinds of nodes represent computed by-products
-                // that we don't hash directly; instead, they should
-                // have some transitive dependency on a Hir or
-                // MetaData node, so we'll just hash that
-                None
-            }
-        }
-    }
-
-    fn metadata_hash<K, C>(&mut self,
-                           key: K,
-                           cnum: CrateNum,
-                           cache: C)
-                           -> Fingerprint
-        where K: Hash + Eq + Debug,
-              C: Fn(&mut Self) -> &mut FxHashMap<K, Fingerprint>,
-    {
-        debug!("metadata_hash(key={:?})", key);
-
-        debug_assert!(cnum != LOCAL_CRATE);
-        loop {
-            // check whether we have a result cached for this def-id
-            if let Some(&hash) = cache(self).get(&key) {
-                return hash;
-            }
-
-            // check whether we did not find detailed metadata for this
-            // krate; in that case, we just use the krate's overall hash
-            if let Some(&svh) = self.crate_hashes.get(&cnum) {
-                // micro-"optimization": avoid a cache miss if we ask
-                // for metadata from this particular def-id again.
-                let fingerprint = svh_to_fingerprint(svh);
-                cache(self).insert(key, fingerprint);
-
-                return fingerprint;
-            }
-
-            // otherwise, load the data and repeat.
-            self.load_data(cnum);
-            assert!(self.crate_hashes.contains_key(&cnum));
-        }
-    }
-
-    fn load_data(&mut self, cnum: CrateNum) {
-        debug!("load_data(cnum={})", cnum);
-
-        let svh = self.tcx.crate_hash(cnum);
-        let old = self.crate_hashes.insert(cnum, svh);
-        debug!("load_data: svh={}", svh);
-        assert!(old.is_none(), "loaded data for crate {:?} twice", cnum);
-
-        if let Some(session_dir) = find_metadata_hashes_for(self.tcx, cnum) {
-            debug!("load_data: session_dir={:?}", session_dir);
-
-            // Lock the directory we'll be reading  the hashes from.
-            let lock_file_path = lock_file_path(&session_dir);
-            let _lock = match flock::Lock::new(&lock_file_path,
-                                               false,   // don't wait
-                                               false,   // don't create the lock-file
-                                               false) { // shared lock
-                Ok(lock) => lock,
-                Err(err) => {
-                    debug!("Could not acquire lock on `{}` while trying to \
-                            load metadata hashes: {}",
-                            lock_file_path.display(),
-                            err);
-
-                    // Could not acquire the lock. The directory is probably in
-                    // in the process of being deleted. It's OK to just exit
-                    // here. It's the same scenario as if the file had not
-                    // existed in the first place.
-                    return
-                }
-            };
-
-            let hashes_file_path = metadata_hash_import_path(&session_dir);
-
-            match file_format::read_file(self.tcx.sess, &hashes_file_path)
-            {
-                Ok(Some(data)) => {
-                    match self.load_from_data(cnum, &data, svh) {
-                        Ok(()) => { }
-                        Err(err) => {
-                            bug!("decoding error in dep-graph from `{}`: {}",
-                                 &hashes_file_path.display(), err);
-                        }
-                    }
-                }
-                Ok(None) => {
-                    // If the file is not found, that's ok.
-                }
-                Err(err) => {
-                    self.tcx.sess.err(
-                        &format!("could not load dep information from `{}`: {}",
-                                 hashes_file_path.display(), err));
-                }
-            }
-        }
-    }
-
-    fn load_from_data(&mut self,
-                      cnum: CrateNum,
-                      data: &[u8],
-                      expected_svh: Svh) -> Result<(), String> {
-        debug!("load_from_data(cnum={})", cnum);
-
-        // Load up the hashes for the def-ids from this crate.
-        let mut decoder = Decoder::new(data, 0);
-        let svh_in_hashes_file = Svh::decode(&mut decoder)?;
-
-        if svh_in_hashes_file != expected_svh {
-            // We should not be able to get here. If we do, then
-            // `fs::find_metadata_hashes_for()` has messed up.
-            bug!("mismatch between SVH in crate and SVH in incr. comp. hashes")
-        }
-
-        let serialized_hashes = SerializedMetadataHashes::decode(&mut decoder)?;
-        for serialized_hash in serialized_hashes.entry_hashes {
-            // the hashes are stored with just a def-index, which is
-            // always relative to the old crate; convert that to use
-            // our internal crate number
-            let def_id = DefId { krate: cnum, index: serialized_hash.def_index };
-
-            // record the hash for this dep-node
-            let old = self.metadata_hashes.insert(def_id, serialized_hash.hash);
-            debug!("load_from_data: def_id={:?} hash={}", def_id, serialized_hash.hash);
-            assert!(old.is_none(), "already have hash for {:?}", def_id);
-        }
-
-        Ok(())
-    }
-}
-
-fn svh_to_fingerprint(svh: Svh) -> Fingerprint {
-    Fingerprint::from_smaller_hash(svh.as_u64())
-}
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 9865ea8c285..6d019a25ed3 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -10,22 +10,19 @@
 
 //! Code to save/load the dep-graph from files.
 
-use rustc::dep_graph::{DepNode, WorkProductId, DepKind};
-use rustc::hir::def_id::DefId;
+use rustc::dep_graph::{DepNode, WorkProductId, DepKind, PreviousDepGraph};
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc::util::nodemap::DefIdMap;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_serialize::Decodable as RustcDecodable;
 use rustc_serialize::opaque::Decoder;
 use std::path::{Path};
 
-use IncrementalHashesMap;
 use super::data::*;
-use super::dirty_clean;
-use super::hash::*;
 use super::fs::*;
 use super::file_format;
 use super::work_product;
@@ -40,16 +37,16 @@ pub type DirtyNodes = FxHashMap<DepNodeIndex, DepNodeIndex>;
 /// early in compilation, before we've really done any work, but
 /// actually it doesn't matter all that much.) See `README.md` for
 /// more general overview.
-pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                incremental_hashes_map: &IncrementalHashesMap) {
+pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    tcx.allocate_metadata_dep_nodes();
+    tcx.precompute_in_scope_traits_hashes();
     if tcx.sess.incr_session_load_dep_graph() {
         let _ignore = tcx.dep_graph.in_ignore();
-        load_dep_graph_if_exists(tcx, incremental_hashes_map);
+        load_dep_graph_if_exists(tcx);
     }
 }
 
-fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      incremental_hashes_map: &IncrementalHashesMap) {
+fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let dep_graph_path = dep_graph_path(tcx.sess);
     let dep_graph_data = match load_data(tcx.sess, &dep_graph_path) {
         Some(p) => p,
@@ -62,7 +59,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         None => return // no file
     };
 
-    match decode_dep_graph(tcx, incremental_hashes_map, &dep_graph_data, &work_products_data) {
+    match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) {
         Ok(dirty_nodes) => dirty_nodes,
         Err(err) => {
             tcx.sess.warn(
@@ -105,7 +102,7 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool {
         DepKind::Hir |
         DepKind::HirBody |
         DepKind::InScopeTraits |
-        DepKind::MetaData => {
+        DepKind::CrateMetadata => {
             dep_node.extract_def_id(tcx).is_some()
         }
         _ => {
@@ -117,7 +114,6 @@ fn does_still_exist(tcx: TyCtxt, dep_node: &DepNode) -> bool {
 /// Decode the dep graph and load the edges/nodes that are still clean
 /// into `tcx.dep_graph`.
 pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  incremental_hashes_map: &IncrementalHashesMap,
                                   dep_graph_data: &[u8],
                                   work_products_data: &[u8])
                                   -> Result<(), String>
@@ -150,7 +146,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Compute the set of nodes from the old graph where some input
     // has changed or been removed.
     let dirty_raw_nodes = initial_dirty_nodes(tcx,
-                                              incremental_hashes_map,
                                               &serialized_dep_graph.nodes,
                                               &serialized_dep_graph.hashes);
     let dirty_raw_nodes = transitive_dirty_nodes(&serialized_dep_graph,
@@ -190,31 +185,21 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // dirty.
     reconcile_work_products(tcx, work_products, &clean_work_products);
 
-    dirty_clean::check_dirty_clean_annotations(tcx,
-                                               &serialized_dep_graph.nodes,
-                                               &dirty_raw_nodes);
-
-    load_prev_metadata_hashes(tcx,
-                              &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut());
     Ok(())
 }
 
 /// Computes which of the original set of def-ids are dirty. Stored in
 /// a bit vector where the index is the DefPathIndex.
 fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 incremental_hashes_map: &IncrementalHashesMap,
                                  nodes: &IndexVec<DepNodeIndex, DepNode>,
                                  serialized_hashes: &[(DepNodeIndex, Fingerprint)])
                                  -> DirtyNodes {
-    let mut hcx = HashContext::new(tcx, incremental_hashes_map);
     let mut dirty_nodes = FxHashMap();
 
     for &(dep_node_index, prev_hash) in serialized_hashes {
         let dep_node = nodes[dep_node_index];
         if does_still_exist(tcx, &dep_node) {
-            let current_hash = hcx.hash(&dep_node).unwrap_or_else(|| {
-                bug!("Cannot find current ICH for input that still exists?")
-            });
+            let current_hash = tcx.dep_graph.fingerprint_of(&dep_node);
 
             if current_hash == prev_hash {
                 debug!("initial_dirty_nodes: {:?} is clean (hash={:?})",
@@ -310,11 +295,12 @@ fn delete_dirty_work_product(tcx: TyCtxt,
     work_product::delete_workproduct_files(tcx.sess, &swp.work_product);
 }
 
-fn load_prev_metadata_hashes(tcx: TyCtxt,
-                             output: &mut FxHashMap<DefId, Fingerprint>) {
+pub fn load_prev_metadata_hashes(tcx: TyCtxt) -> DefIdMap<Fingerprint> {
+    let mut output = DefIdMap();
+
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         // Previous metadata hashes are only needed for testing.
-        return
+        return output
     }
 
     debug!("load_prev_metadata_hashes() - Loading previous metadata hashes");
@@ -324,7 +310,7 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
     if !file_path.exists() {
         debug!("load_prev_metadata_hashes() - Couldn't find file containing \
                 hashes at `{}`", file_path.display());
-        return
+        return output
     }
 
     debug!("load_prev_metadata_hashes() - File: {}", file_path.display());
@@ -334,12 +320,12 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
         Ok(None) => {
             debug!("load_prev_metadata_hashes() - File produced by incompatible \
                     compiler version: {}", file_path.display());
-            return
+            return output
         }
         Err(err) => {
             debug!("load_prev_metadata_hashes() - Error reading file `{}`: {}",
                    file_path.display(), err);
-            return
+            return output
         }
     };
 
@@ -363,6 +349,8 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
 
     debug!("load_prev_metadata_hashes() - successfully loaded {} hashes",
            serialized_hashes.index_map.len());
+
+    output
 }
 
 fn process_edge<'a, 'tcx, 'edges>(
@@ -421,7 +409,7 @@ fn process_edge<'a, 'tcx, 'edges>(
     // clean target because removing the input would have dirtied the input
     // node and transitively dirtied the target.
     debug_assert!(match nodes[source].kind {
-        DepKind::Hir | DepKind::HirBody | DepKind::MetaData => {
+        DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => {
             does_still_exist(tcx, &nodes[source])
         }
         _ => true,
@@ -438,3 +426,38 @@ fn process_edge<'a, 'tcx, 'edges>(
         }
     }
 }
+
+pub fn load_dep_graph_new(sess: &Session) -> PreviousDepGraph {
+    use rustc::dep_graph::SerializedDepGraph as SerializedDepGraphNew;
+
+    let empty = PreviousDepGraph::new(SerializedDepGraphNew::new());
+
+    if sess.opts.incremental.is_none() {
+        return empty
+    }
+
+    if let Some(bytes) = load_data(sess, &dep_graph_path_new(sess)) {
+        let mut decoder = Decoder::new(&bytes, 0);
+        let prev_commandline_args_hash = u64::decode(&mut decoder)
+            .expect("Error reading commandline arg hash from cached dep-graph");
+
+        if prev_commandline_args_hash != sess.opts.dep_tracking_hash() {
+            if sess.opts.debugging_opts.incremental_info {
+                eprintln!("incremental: completely ignoring cache because of \
+                           differing commandline arguments");
+            }
+            // We can't reuse the cache, purge it.
+            debug!("load_dep_graph_new: differing commandline arg hashes");
+
+            // No need to do any further work
+            return empty
+        }
+
+        let dep_graph = SerializedDepGraphNew::decode(&mut decoder)
+            .expect("Error reading cached dep-graph");
+
+        PreviousDepGraph::new(dep_graph)
+    } else {
+        empty
+    }
+}
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index fb330813226..688d8add57e 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -15,7 +15,6 @@
 mod data;
 mod dirty_clean;
 mod fs;
-mod hash;
 mod load;
 mod preds;
 mod save;
@@ -26,6 +25,7 @@ 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::load_dep_graph_new;
 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/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs
index 5483134523c..a552a27c62a 100644
--- a/src/librustc_incremental/persist/preds/mod.rs
+++ b/src/librustc_incremental/persist/preds/mod.rs
@@ -10,10 +10,10 @@
 
 use rustc::dep_graph::{DepGraphQuery, DepNode, DepKind};
 use rustc::ich::Fingerprint;
+use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::{Graph, NodeIndex};
 
-use super::hash::*;
 
 mod compress;
 
@@ -40,15 +40,13 @@ pub struct Predecessors<'query> {
 }
 
 impl<'q> Predecessors<'q> {
-    pub fn new(query: &'q DepGraphQuery, hcx: &mut HashContext) -> Self {
-        let tcx = hcx.tcx;
-
+    pub fn new(tcx: TyCtxt, query: &'q DepGraphQuery) -> Self {
         // Find the set of "start nodes". These are nodes that we will
         // possibly query later.
         let is_output = |node: &DepNode| -> bool {
             match node.kind {
                 DepKind::WorkProduct => true,
-                DepKind::MetaData => {
+                DepKind::CrateMetadata => {
                     // We do *not* create dep-nodes for the current crate's
                     // metadata anymore, just for metadata that we import/read
                     // from other crates.
@@ -66,7 +64,7 @@ impl<'q> Predecessors<'q> {
         // Reduce the graph to the most important nodes.
         let compress::Reduction { graph, input_nodes } =
             compress::reduce_graph(&query.graph,
-                                   |n| HashContext::is_hashable(tcx, n),
+                                   |n| n.kind.is_input(),
                                    |n| is_output(n));
 
         let mut hashes = FxHashMap();
@@ -74,7 +72,7 @@ impl<'q> Predecessors<'q> {
             let input = *graph.node_data(input_index);
             debug!("computing hash for input node `{:?}`", input);
             hashes.entry(input)
-                  .or_insert_with(|| hcx.hash(input).unwrap());
+                  .or_insert_with(|| tcx.dep_graph.fingerprint_of(&input));
         }
 
         if tcx.sess.opts.debugging_opts.query_dep_graph {
@@ -89,7 +87,7 @@ impl<'q> Predecessors<'q> {
 
             for node in hir_nodes {
                 hashes.entry(node)
-                      .or_insert_with(|| hcx.hash(node).unwrap());
+                      .or_insert_with(|| tcx.dep_graph.fingerprint_of(&node));
             }
         }
 
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 65fbaf1ad04..fd699229f1b 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -15,26 +15,27 @@ use rustc::ich::Fingerprint;
 use rustc::middle::cstore::EncodedMetadataHashes;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
+use rustc::util::common::time;
+use rustc::util::nodemap::DefIdMap;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph;
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_serialize::opaque::Encoder;
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
 use std::path::PathBuf;
 
-use IncrementalHashesMap;
 use super::data::*;
-use super::hash::*;
 use super::preds::*;
 use super::fs::*;
 use super::dirty_clean;
 use super::file_format;
 use super::work_product;
 
+use super::load::load_prev_metadata_hashes;
+
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                incremental_hashes_map: IncrementalHashesMap,
                                 metadata_hashes: &EncodedMetadataHashes,
                                 svh: Svh) {
     debug!("save_dep_graph()");
@@ -44,15 +45,14 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return;
     }
 
-    let query = tcx.dep_graph.query();
-
-    if tcx.sess.opts.debugging_opts.incremental_info {
-        eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes());
-        eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges());
-    }
+    // We load the previous metadata hashes now before overwriting the file
+    // (if we need them for testing).
+    let prev_metadata_hashes = if tcx.sess.opts.debugging_opts.query_dep_graph {
+        load_prev_metadata_hashes(tcx)
+    } else {
+        DefIdMap()
+    };
 
-    let mut hcx = HashContext::new(tcx, &incremental_hashes_map);
-    let preds = Predecessors::new(&query, &mut hcx);
     let mut current_metadata_hashes = FxHashMap();
 
     // IMPORTANT: We are saving the metadata hashes *before* the dep-graph,
@@ -69,13 +69,29 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            e));
     }
 
-    save_in(sess,
-            dep_graph_path(sess),
-            |e| encode_dep_graph(tcx, &preds, e));
+    time(sess.time_passes(), "persist dep-graph (old)", || {
+        let query = tcx.dep_graph.query();
+
+        if tcx.sess.opts.debugging_opts.incremental_info {
+            eprintln!("incremental: {} nodes in dep-graph", query.graph.len_nodes());
+            eprintln!("incremental: {} edges in dep-graph", query.graph.len_edges());
+        }
+
+        let preds = Predecessors::new(tcx, &query);
+        save_in(sess,
+                dep_graph_path(sess),
+                |e| encode_dep_graph(tcx, &preds, e));
+    });
 
-    let prev_metadata_hashes = incremental_hashes_map.prev_metadata_hashes.borrow();
+    time(sess.time_passes(), "persist dep-graph (new)", || {
+        save_in(sess,
+                dep_graph_path_new(sess),
+                |e| encode_dep_graph_new(tcx, e));
+    });
+
+    dirty_clean::check_dirty_clean_annotations(tcx);
     dirty_clean::check_dirty_clean_metadata(tcx,
-                                            &*prev_metadata_hashes,
+                                            &prev_metadata_hashes,
                                             &current_metadata_hashes);
 }
 
@@ -166,6 +182,19 @@ fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
     }
 }
 
+fn encode_dep_graph_new(tcx: TyCtxt,
+                        encoder: &mut Encoder)
+                        -> io::Result<()> {
+    // First encode the commandline arguments hash
+    tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
+
+    // Encode the graph data.
+    let serialized_graph = tcx.dep_graph.serialize();
+    serialized_graph.encode(encoder)?;
+
+    Ok(())
+}
+
 pub fn encode_dep_graph(tcx: TyCtxt,
                         preds: &Predecessors,
                         encoder: &mut Encoder)
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index d4b8f0a4924..cbc012a65fa 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
         self.check_snake_case(cx,
                               "lifetime",
-                              &t.lifetime.name.as_str(),
+                              &t.lifetime.name.name().as_str(),
                               Some(t.lifetime.span));
     }
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 439cc3a4b84..b97920dd18b 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -153,6 +153,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
         };
 
         let mut fn_warned = false;
+        let mut op_warned = false;
         if cx.tcx.sess.features.borrow().fn_must_use {
             let maybe_def = match expr.node {
                 hir::ExprCall(ref callee, _) => {
@@ -172,9 +173,24 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
                 let def_id = def.def_id();
                 fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
             }
+
+            if let hir::ExprBinary(bin_op, ..) = expr.node {
+                match bin_op.node {
+                    // Hardcoding the comparison operators here seemed more
+                    // expedient than the refactoring that would be needed to
+                    // look up the `#[must_use]` attribute which does exist on
+                    // the comparison trait methods
+                    hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => {
+                        let msg = "unused comparison which must be used";
+                        cx.span_lint(UNUSED_MUST_USE, expr.span, msg);
+                        op_warned = true;
+                    },
+                    _ => {},
+                }
+            }
         }
 
-        if !(ty_warned || fn_warned) {
+        if !(ty_warned || fn_warned || op_warned) {
             cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
         }
 
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 1ed2cbab65f..de5add56b76 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -18,4 +18,4 @@ rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.50"
+cc = "1.0"
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 393aa7fa43b..dde7a38efc7 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate gcc;
+extern crate cc;
 extern crate build_helper;
 
 use std::process::Command;
@@ -136,7 +136,7 @@ fn main() {
     let mut cmd = Command::new(&llvm_config);
     cmd.arg("--cxxflags");
     let cxxflags = output(&mut cmd);
-    let mut cfg = gcc::Build::new();
+    let mut cfg = cc::Build::new();
     cfg.warnings(false);
     for flag in cxxflags.split_whitespace() {
         // Ignore flags like `-m64` when we're doing a cross build
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index f785d7bd407..8eacc21ab00 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -55,9 +55,14 @@ macro_rules! provide {
                 let ($def_id, $other) = def_id_arg.into_args();
                 assert!(!$def_id.is_local());
 
-                let def_path_hash = $tcx.def_path_hash($def_id);
-                let dep_node = def_path_hash.to_dep_node(::rustc::dep_graph::DepKind::MetaData);
-
+                let def_path_hash = $tcx.def_path_hash(DefId {
+                    krate: $def_id.krate,
+                    index: CRATE_DEF_INDEX
+                });
+                let dep_node = def_path_hash
+                    .to_dep_node(::rustc::dep_graph::DepKind::CrateMetadata);
+                // The DepNodeIndex of the DepNode::CrateMetadata should be
+                // cached somewhere, so that we can use read_index().
                 $tcx.dep_graph.read(dep_node);
 
                 let $cdata = $tcx.crate_data_as_rc_any($def_id.krate);
@@ -379,6 +384,16 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(cnum).name
     }
 
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> Symbol
+    {
+        self.get_crate_data(cnum).disambiguator()
+    }
+
+    fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh
+    {
+        self.get_crate_data(cnum).hash()
+    }
+
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index 063cbc77559..902e2de841f 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -173,14 +173,23 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
         let span = stmt.source_info.span;
         match stmt.kind {
             StatementKind::Assign(ref lhs, ref rhs) => {
+                // NOTE: NLL RFC calls for *shallow* write; using Deep
+                // for short-term compat w/ AST-borrowck. Also, switch
+                // to shallow requires to dataflow: "if this is an
+                // assignment `lv = <rvalue>`, then any loan for some
+                // path P of which `lv` is a prefix is killed."
                 self.mutate_lvalue(ContextKind::AssignLhs.new(location),
-                                   (lhs, span), JustWrite, flow_state);
+                                   (lhs, span), Deep, JustWrite, flow_state);
+
                 self.consume_rvalue(ContextKind::AssignRhs.new(location),
                                     (rhs, span), location, flow_state);
             }
             StatementKind::SetDiscriminant { ref lvalue, variant_index: _ } => {
                 self.mutate_lvalue(ContextKind::SetDiscrim.new(location),
-                                   (lvalue, span), JustWrite, flow_state);
+                                   (lvalue, span),
+                                   Shallow(Some(ArtificialField::Discriminant)),
+                                   JustWrite,
+                                   flow_state);
             }
             StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
                 for (o, output) in asm.outputs.iter().zip(outputs) {
@@ -192,6 +201,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
                     } else {
                         self.mutate_lvalue(ContextKind::InlineAsm.new(location),
                                            (output, span),
+                                           Deep,
                                            if o.is_rw { WriteAndRead } else { JustWrite },
                                            flow_state);
                     }
@@ -209,15 +219,15 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
             StatementKind::Nop |
             StatementKind::Validate(..) |
             StatementKind::StorageLive(..) => {
-                // ignored by borrowck
+                // `Nop`, `Validate`, and `StorageLive` are irrelevant
+                // to borrow check.
             }
 
             StatementKind::StorageDead(local) => {
-                // causes non-drop values to be dropped.
-                self.consume_lvalue(ContextKind::StorageDead.new(location),
-                                    ConsumeKind::Consume,
-                                    (&Lvalue::Local(local), span),
-                                    flow_state)
+                self.access_lvalue(ContextKind::StorageDead.new(location),
+                                   (&Lvalue::Local(local), span),
+                                   (Shallow(None), Write(WriteKind::StorageDead)),
+                                   flow_state);
             }
         }
     }
@@ -246,7 +256,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
                                              target: _,
                                              unwind: _ } => {
                 self.mutate_lvalue(ContextKind::DropAndReplace.new(loc),
-                                   (drop_lvalue, span), JustWrite, flow_state);
+                                   (drop_lvalue, span),
+                                   Deep,
+                                   JustWrite,
+                                   flow_state);
                 self.consume_operand(ContextKind::DropAndReplace.new(loc),
                                      ConsumeKind::Drop,
                                      (new_value, span), flow_state);
@@ -262,7 +275,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
                 }
                 if let Some((ref dest, _/*bb*/)) = *destination {
                     self.mutate_lvalue(ContextKind::CallDest.new(loc),
-                                       (dest, span), JustWrite, flow_state);
+                                       (dest, span),
+                                       Deep,
+                                       JustWrite,
+                                       flow_state);
                 }
             }
             TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
@@ -309,29 +325,121 @@ enum ConsumeKind { Drop, Consume }
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum Control { Continue, Break }
 
+use self::ShallowOrDeep::{Shallow, Deep};
+use self::ReadOrWrite::{Read, Write};
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ArtificialField {
+    Discriminant,
+    ArrayLength,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ShallowOrDeep {
+    /// From the RFC: "A *shallow* access means that the immediate
+    /// fields reached at LV are accessed, but references or pointers
+    /// found within are not dereferenced. Right now, the only access
+    /// that is shallow is an assignment like `x = ...;`, which would
+    /// be a *shallow write* of `x`."
+    Shallow(Option<ArtificialField>),
+
+    /// From the RFC: "A *deep* access means that all data reachable
+    /// through the given lvalue may be invalidated or accesses by
+    /// this action."
+    Deep,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ReadOrWrite {
+    /// From the RFC: "A *read* means that the existing data may be
+    /// read, but will not be changed."
+    Read(ReadKind),
+
+    /// From the RFC: "A *write* means that the data may be mutated to
+    /// new values or otherwise invalidated (for example, it could be
+    /// de-initialized, as in a move operation).
+    Write(WriteKind),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ReadKind {
+    Borrow(BorrowKind),
+    Copy,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum WriteKind {
+    StorageDead,
+    MutableBorrow(BorrowKind),
+    Mutate,
+    Move,
+}
+
 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),
+                     kind: (ShallowOrDeep, ReadOrWrite),
+                     flow_state: &InProgress<'b, 'gcx>) {
+        // FIXME: also need to check permissions (e.g. reject mut
+        // borrow of immutable ref, moves through non-`Box`-ref)
+        let (sd, rw) = kind;
+        self.each_borrow_involving_path(
+            context, (sd, lvalue_span.0), flow_state, |this, _index, borrow| {
+                match (rw, borrow.kind) {
+                    (Read(_), BorrowKind::Shared) => {
+                        Control::Continue
+                    }
+                    (Read(kind), BorrowKind::Unique) |
+                    (Read(kind), BorrowKind::Mut) => {
+                        match kind {
+                            ReadKind::Copy =>
+                                this.report_use_while_mutably_borrowed(
+                                    context, lvalue_span, borrow),
+                            ReadKind::Borrow(bk) =>
+                                this.report_conflicting_borrow(
+                                    context, lvalue_span,
+                                    (lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)),
+                        }
+                        Control::Break
+                    }
+                    (Write(kind), _) => {
+                        match kind {
+                            WriteKind::MutableBorrow(bk) =>
+                                this.report_conflicting_borrow(
+                                    context, lvalue_span,
+                                    (lvalue_span.0, bk), (&borrow.lvalue, borrow.kind)),
+                            WriteKind::StorageDead |
+                            WriteKind::Mutate =>
+                                this.report_illegal_mutation_of_borrowed(
+                                    context, lvalue_span, borrow),
+                            WriteKind::Move =>
+                                this.report_move_out_while_borrowed(
+                                    context, lvalue_span, borrow),
+                        }
+                        Control::Break
+                    }
+                }
+            });
+    }
+
     fn mutate_lvalue(&mut self,
                      context: Context,
                      lvalue_span: (&Lvalue<'gcx>, Span),
+                     kind: ShallowOrDeep,
                      mode: MutateMode,
                      flow_state: &InProgress<'b, 'gcx>) {
         // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd.
         match mode {
             MutateMode::WriteAndRead => {
-                self.check_if_path_is_moved(context, lvalue_span, flow_state);
+                self.check_if_path_is_moved(context, "update", lvalue_span, flow_state);
             }
             MutateMode::JustWrite => {
                 self.check_if_assigned_path_is_moved(context, lvalue_span, flow_state);
             }
         }
 
-        // check we don't invalidate any outstanding loans
-        self.each_borrow_involving_path(context,
-                                        lvalue_span.0, flow_state, |this, _index, _data| {
-                                            this.report_illegal_mutation_of_borrowed(context,
-                                                                                     lvalue_span);
-                                            Control::Break
-                                        });
+        self.access_lvalue(context, lvalue_span, (kind, Write(WriteKind::Mutate)), flow_state);
 
         // check for reassignments to immutable local variables
         self.check_if_reassignment_to_immutable_state(context, lvalue_span, flow_state);
@@ -340,11 +448,17 @@ 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),
-                      location: Location,
+                      _location: Location,
                       flow_state: &InProgress<'b, 'gcx>) {
         match *rvalue {
             Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => {
-                self.borrow(context, location, bk, (lvalue, span), flow_state)
+                let access_kind = match bk {
+                    BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
+                    BorrowKind::Unique |
+                    BorrowKind::Mut => (Deep, Write(WriteKind::MutableBorrow(bk))),
+                };
+                self.access_lvalue(context, (lvalue, span), access_kind, flow_state);
+                self.check_if_path_is_moved(context, "borrow", (lvalue, span), flow_state);
             }
 
             Rvalue::Use(ref operand) |
@@ -356,8 +470,14 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 
             Rvalue::Len(ref lvalue) |
             Rvalue::Discriminant(ref lvalue) => {
-                // len(_)/discriminant(_) merely read, not consume.
-                self.check_if_path_is_moved(context, (lvalue, span), flow_state);
+                let af = match *rvalue {
+                    Rvalue::Len(..) => ArtificialField::ArrayLength,
+                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    _ => unreachable!(),
+                };
+                self.access_lvalue(
+                    context, (lvalue, span), (Shallow(Some(af)), Read(ReadKind::Copy)), flow_state);
+                self.check_if_path_is_moved(context, "use", (lvalue, span), flow_state);
             }
 
             Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) |
@@ -388,8 +508,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                        (operand, span): (&Operand<'gcx>, Span),
                        flow_state: &InProgress<'b, 'gcx>) {
         match *operand {
-            Operand::Consume(ref lvalue) =>
-                self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state),
+            Operand::Consume(ref lvalue) => {
+                self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state)
+            }
             Operand::Constant(_) => {}
         }
     }
@@ -405,26 +526,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
             self.fake_infer_ctxt.type_moves_by_default(self.param_env, ty, DUMMY_SP);
         if moves_by_default {
             // move of lvalue: check if this is move of already borrowed path
-            self.each_borrow_involving_path(
-                context, lvalue_span.0, flow_state, |this, _idx, borrow| {
-                    if !borrow.compatible_with(BorrowKind::Mut) {
-                        this.report_move_out_while_borrowed(context, lvalue_span);
-                        Control::Break
-                    } else {
-                        Control::Continue
-                    }
-                });
+            self.access_lvalue(context, lvalue_span, (Deep, Write(WriteKind::Move)), flow_state);
         } else {
             // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs)
-            self.each_borrow_involving_path(
-                context, lvalue_span.0, flow_state, |this, _idx, borrow| {
-                    if !borrow.compatible_with(BorrowKind::Shared) {
-                        this.report_use_while_mutably_borrowed(context, lvalue_span);
-                        Control::Break
-                    } else {
-                        Control::Continue
-                    }
-                });
+            self.access_lvalue(context, lvalue_span, (Deep, Read(ReadKind::Copy)), flow_state);
         }
 
         // Finally, check if path was already moved.
@@ -435,22 +540,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                 // skip this check in that case).
             }
             ConsumeKind::Consume => {
-                self.check_if_path_is_moved(context, lvalue_span, flow_state);
+                self.check_if_path_is_moved(context, "use", lvalue_span, flow_state);
             }
         }
     }
-
-    fn borrow(&mut self,
-              context: Context,
-              location: Location,
-              bk: BorrowKind,
-              lvalue_span: (&Lvalue<'gcx>, Span),
-              flow_state: &InProgress<'b, 'gcx>) {
-        debug!("borrow location: {:?} lvalue: {:?} span: {:?}",
-               location, lvalue_span.0, lvalue_span.1);
-        self.check_if_path_is_moved(context, lvalue_span, flow_state);
-        self.check_for_conflicting_loans(context, location, bk, lvalue_span, flow_state);
-    }
 }
 
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
@@ -487,13 +580,26 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
             if flow_state.inits.curr_state.contains(&mpi) {
                 // may already be assigned before reaching this statement;
                 // report error.
-                self.report_illegal_reassignment(context, (lvalue, span));
+                // FIXME: Not ideal, it only finds the assignment that lexically comes first
+                let assigned_lvalue = &move_data.move_paths[mpi].lvalue;
+                let assignment_stmt = self.mir.basic_blocks().iter().filter_map(|bb| {
+                    bb.statements.iter().find(|stmt| {
+                        if let StatementKind::Assign(ref lv, _) = stmt.kind {
+                            *lv == *assigned_lvalue
+                        } else {
+                            false
+                        }
+                    })
+                }).next().unwrap();
+                self.report_illegal_reassignment(
+                    context, (lvalue, span), assignment_stmt.source_info.span);
             }
         }
     }
 
     fn check_if_path_is_moved(&mut self,
                               context: Context,
+                              desired_action: &str,
                               lvalue_span: (&Lvalue<'gcx>, Span),
                               flow_state: &InProgress<'b, 'gcx>) {
         // FIXME: analogous code in check_loans first maps `lvalue` to
@@ -505,7 +611,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
         if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) {
             if maybe_uninits.curr_state.contains(&mpi) {
                 // find and report move(s) that could cause this to be uninitialized
-                self.report_use_of_moved(context, lvalue_span);
+                self.report_use_of_moved(context, desired_action, lvalue_span);
             } else {
                 // sanity check: initialized on *some* path, right?
                 assert!(flow_state.inits.curr_state.contains(&mpi));
@@ -572,8 +678,8 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                                     // check_loans.rs first maps
                                     // `base` to its base_path.
 
-                                    self.check_if_path_is_moved(context,
-                                                                (base, span), flow_state);
+                                    self.check_if_path_is_moved(
+                                        context, "assignment", (base, span), flow_state);
 
                                     // (base initialized; no need to
                                     // recur further)
@@ -590,72 +696,18 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
             }
         }
     }
-
-    fn check_for_conflicting_loans(&mut self,
-                                   context: Context,
-                                   _location: Location,
-                                   _bk: BorrowKind,
-                                   lvalue_span: (&Lvalue<'gcx>, Span),
-                                   flow_state: &InProgress<'b, 'gcx>) {
-        // NOTE FIXME: The analogous code in old borrowck
-        // check_loans.rs is careful to iterate over every *issued*
-        // loan, as opposed to just the in scope ones.
-        //
-        // (Or if you prefer, all the *other* iterations over loans
-        // only consider loans that are in scope of some given
-        // region::Scope)
-        //
-        // The (currently skeletal) code here does not encode such a
-        // distinction, which means it is almost certainly over
-        // looking something.
-        //
-        // (It is probably going to reject code that should be
-        // accepted, I suspect, by treated issued-but-out-of-scope
-        // loans as issued-and-in-scope, and thus causing them to
-        // interfere with other loans.)
-        //
-        // However, I just want to get something running, especially
-        // since I am trying to move into new territory with NLL, so
-        // lets get this going first, and then address the issued vs
-        // in-scope distinction later.
-
-        let state = &flow_state.borrows;
-        let data = &state.base_results.operator().borrows();
-
-        debug!("check_for_conflicting_loans location: {:?}", _location);
-
-        // does any loan generated here conflict with a previously issued loan?
-        let mut loans_generated = 0;
-        for (g, gen) in state.elems_generated().map(|g| (g, &data[g])) {
-            loans_generated += 1;
-            for (i, issued) in state.elems_incoming().map(|i| (i, &data[i])) {
-                debug!("check_for_conflicting_loans gen: {:?} issued: {:?} conflicts: {}",
-                       (g, gen, self.base_path(&gen.lvalue),
-                        self.restrictions(&gen.lvalue).collect::<Vec<_>>()),
-                       (i, issued, self.base_path(&issued.lvalue),
-                        self.restrictions(&issued.lvalue).collect::<Vec<_>>()),
-                       self.conflicts_with(gen, issued));
-                if self.conflicts_with(gen, issued) {
-                    self.report_conflicting_borrow(context, lvalue_span, gen, issued);
-                }
-            }
-        }
-
-        // MIR statically ensures each statement gens *at most one*
-        // loan; mutual conflict (within a statement) can't arise.
-        //
-        // As safe-guard, assert that above property actually holds.
-        assert!(loans_generated <= 1);
-    } }
+}
 
 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,
-                                     lvalue: &Lvalue<'gcx>,
+                                     access_lvalue: (ShallowOrDeep, &Lvalue<'gcx>),
                                      flow_state: &InProgress<'b, 'gcx>,
                                      mut op: F)
         where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>) -> Control
     {
+        let (access, lvalue) = access_lvalue;
+
         // FIXME: analogous code in check_loans first maps `lvalue` to
         // its base_path.
 
@@ -664,228 +716,182 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
 
         // check for loan restricting path P being used. Accounts for
         // borrows of P, P.a.b, etc.
-        for i in flow_state.borrows.elems_incoming() {
-            // FIXME: check_loans.rs filtered this to "in scope"
-            // loans; i.e. it took a scope S and checked that each
-            // restriction's kill_scope was a superscope of S.
+        'next_borrow: for i in flow_state.borrows.elems_incoming() {
             let borrowed = &data[i];
-            for restricted in self.restrictions(&borrowed.lvalue) {
-                if restricted == lvalue {
+
+            // Is `lvalue` (or a prefix of it) already borrowed? If
+            // so, that's relevant.
+            //
+            // FIXME: Differs from AST-borrowck; includes drive-by fix
+            // to #38899. Will probably need back-compat mode flag.
+            for accessed_prefix in self.prefixes(lvalue, PrefixSet::All) {
+                if *accessed_prefix == borrowed.lvalue {
+                    // FIXME: pass in prefix here too? And/or enum
+                    // describing case we are in?
                     let ctrl = op(self, i, borrowed);
                     if ctrl == Control::Break { return; }
                 }
             }
-        }
 
-        // check for loans (not restrictions) on any base path.
-        // e.g. Rejects `{ let x = &mut a.b; let y = a.b.c; }`,
-        // since that moves out of borrowed path `a.b`.
-        //
-        // Limiting to loans (not restrictions) keeps this one
-        // working: `{ let x = &mut a.b; let y = a.c; }`
-        let mut cursor = lvalue;
-        loop {
-            // FIXME: check_loans.rs invoked `op` *before* cursor
-            // shift here.  Might just work (and even avoid redundant
-            // errors?) given code above?  But for now, I want to try
-            // doing what I think is more "natural" check.
-            for i in flow_state.borrows.elems_incoming() {
-                let borrowed = &data[i];
-                if borrowed.lvalue == *cursor {
+            // Is `lvalue` a prefix (modulo access type) of the
+            // `borrowed.lvalue`? If so, that's relevant.
+
+            let prefix_kind = match access {
+                Shallow(Some(ArtificialField::Discriminant)) |
+                Shallow(Some(ArtificialField::ArrayLength)) => {
+                    // The discriminant and array length are like
+                    // additional fields on the type; they do not
+                    // overlap any existing data there. Furthermore,
+                    // they cannot actually be a prefix of any
+                    // borrowed lvalue (at least in MIR as it is
+                    // currently.)
+                    continue 'next_borrow;
+                }
+                Shallow(None) => PrefixSet::Shallow,
+                Deep => PrefixSet::Supporting,
+            };
+
+            for borrowed_prefix in self.prefixes(&borrowed.lvalue, prefix_kind) {
+                if borrowed_prefix == lvalue {
+                    // FIXME: pass in prefix here too? And/or enum
+                    // describing case we are in?
                     let ctrl = op(self, i, borrowed);
                     if ctrl == Control::Break { return; }
                 }
             }
-
-            match *cursor {
-                Lvalue::Local(_) | Lvalue::Static(_) => break,
-                Lvalue::Projection(ref proj) => cursor = &proj.base,
-            }
         }
     }
 }
 
-mod restrictions {
-    use super::MirBorrowckCtxt;
+use self::prefixes::PrefixSet;
+
+/// From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
+/// lvalue are formed by stripping away fields and derefs, except that
+/// we stop when we reach the deref of a shared reference. [...] "
+///
+/// "Shallow prefixes are found by stripping away fields, but stop at
+/// any dereference. So: writing a path like `a` is illegal if `a.b`
+/// is borrowed. But: writing `a` is legal if `*a` is borrowed,
+/// whether or not `a` is a shared or mutable reference. [...] "
+mod prefixes {
+    use super::{MirBorrowckCtxt};
 
     use rustc::hir;
     use rustc::ty::{self, TyCtxt};
     use rustc::mir::{Lvalue, Mir, ProjectionElem};
 
-    pub(super) struct Restrictions<'c, 'tcx: 'c> {
+    pub(super) struct Prefixes<'c, 'tcx: 'c> {
         mir: &'c Mir<'tcx>,
         tcx: TyCtxt<'c, 'tcx, 'tcx>,
-        lvalue_stack: Vec<&'c Lvalue<'tcx>>,
+        kind: PrefixSet,
+        next: Option<&'c Lvalue<'tcx>>,
+    }
+
+    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
+    pub(super) enum PrefixSet {
+        All,
+        Shallow,
+        Supporting,
     }
 
     impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
-        pub(super) fn restrictions<'d>(&self,
-                                       lvalue: &'d Lvalue<'gcx>)
-                                       -> Restrictions<'d, 'gcx> where 'b: 'd
+        pub(super) fn prefixes<'d>(&self,
+                                   lvalue: &'d Lvalue<'gcx>,
+                                   kind: PrefixSet)
+                                   -> Prefixes<'d, 'gcx> where 'b: 'd
         {
-            let lvalue_stack = if self.has_restrictions(lvalue) { vec![lvalue] } else { vec![] };
-            Restrictions { lvalue_stack: lvalue_stack, mir: self.mir, tcx: self.tcx }
+            Prefixes { next: Some(lvalue), kind, mir: self.mir, tcx: self.tcx }
         }
+    }
+
+    impl<'c, 'tcx> Iterator for Prefixes<'c, 'tcx> {
+        type Item = &'c Lvalue<'tcx>;
+        fn next(&mut self) -> Option<Self::Item> {
+            let mut cursor = match self.next {
+                None => return None,
+                Some(lvalue) => lvalue,
+            };
 
-        fn has_restrictions(&self, lvalue: &Lvalue<'gcx>) -> bool {
-            let mut cursor = lvalue;
-            loop {
+            // Post-processing `lvalue`: Enqueue any remaining
+            // work. Also, `lvalue` may not be a prefix itself, but
+            // may hold one further down (e.g. we never return
+            // downcasts here, but may return a base of a downcast).
+
+            'cursor: loop {
                 let proj = match *cursor {
-                    Lvalue::Local(_) => return true,
-                    Lvalue::Static(_) => return false,
+                    Lvalue::Local(_) | // search yielded this leaf
+                    Lvalue::Static(_) => {
+                        self.next = None;
+                        return Some(cursor);
+                    }
+
                     Lvalue::Projection(ref proj) => proj,
                 };
+
                 match proj.elem {
-                    ProjectionElem::Index(..) |
-                    ProjectionElem::ConstantIndex { .. } |
+                    ProjectionElem::Field(_/*field*/, _/*ty*/) => {
+                        // FIXME: add union handling
+                        self.next = Some(&proj.base);
+                        return Some(cursor);
+                    }
                     ProjectionElem::Downcast(..) |
                     ProjectionElem::Subslice { .. } |
-                    ProjectionElem::Field(_/*field*/, _/*ty*/) => {
+                    ProjectionElem::ConstantIndex { .. } |
+                    ProjectionElem::Index(_) => {
                         cursor = &proj.base;
-                        continue;
+                        continue 'cursor;
                     }
                     ProjectionElem::Deref => {
-                        let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                        match ty.sty {
-                            ty::TyRawPtr(_) => {
-                                return false;
-                            }
-                            ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                                // FIXME: do I need to check validity of
-                                // region here though? (I think the original
-                                // check_loans code did, like readme says)
-                                return false;
-                            }
-                            ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                                cursor = &proj.base;
-                                continue;
-                            }
-                            ty::TyAdt(..) if ty.is_box() => {
-                                cursor = &proj.base;
-                                continue;
-                            }
-                            _ => {
-                                panic!("unknown type fed to Projection Deref.");
-                            }
-                        }
+                        // (handled below)
                     }
                 }
-            }
-        }
-    }
 
-    impl<'c, 'tcx> Iterator for Restrictions<'c, 'tcx> {
-        type Item = &'c Lvalue<'tcx>;
-        fn next(&mut self) -> Option<Self::Item> {
-            'pop: loop {
-                let lvalue = match self.lvalue_stack.pop() {
-                    None => return None,
-                    Some(lvalue) => lvalue,
-                };
+                assert_eq!(proj.elem, ProjectionElem::Deref);
 
-                // `lvalue` may not be a restriction itself, but may
-                // hold one further down (e.g. we never return
-                // downcasts here, but may return a base of a
-                // downcast).
-                //
-                // Also, we need to enqueue any additional
-                // subrestrictions that it implies, since we can only
-                // return from from this call alone.
-
-                let mut cursor = lvalue;
-                'cursor: loop {
-                    let proj = match *cursor {
-                        Lvalue::Local(_) => return Some(cursor), // search yielded this leaf
-                        Lvalue::Static(_) => continue 'pop, // fruitless leaf; try next on stack
-                        Lvalue::Projection(ref proj) => proj,
-                    };
-
-                    match proj.elem {
-                        ProjectionElem::Field(_/*field*/, _/*ty*/) => {
-                            // FIXME: add union handling
-                            self.lvalue_stack.push(&proj.base);
-                            return Some(cursor);
-                        }
-                        ProjectionElem::Downcast(..) |
-                        ProjectionElem::Subslice { .. } |
-                        ProjectionElem::ConstantIndex { .. } |
-                        ProjectionElem::Index(_) => {
-                            cursor = &proj.base;
-                            continue 'cursor;
-                        }
-                        ProjectionElem::Deref => {
-                            // (handled below)
-                        }
+                match self.kind {
+                    PrefixSet::Shallow => {
+                        // shallow prefixes are found by stripping away
+                        // fields, but stop at *any* dereference.
+                        // So we can just stop the traversal now.
+                        self.next = None;
+                        return Some(cursor);
                     }
+                    PrefixSet::All => {
+                        // all prefixes: just blindly enqueue the base
+                        // of the projection
+                        self.next = Some(&proj.base);
+                        return Some(cursor);
+                    }
+                    PrefixSet::Supporting => {
+                        // fall through!
+                    }
+                }
 
-                    assert_eq!(proj.elem, ProjectionElem::Deref);
-
-                    let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                    match ty.sty {
-                        ty::TyRawPtr(_) => {
-                            // borrowck ignores raw ptrs; treat analogous to imm borrow
-                            continue 'pop;
-                        }
-                        // R-Deref-Imm-Borrowed
-                        ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                            // immutably-borrowed referents do not
-                            // have recursively-implied restrictions
-                            // (because preventing actions on `*LV`
-                            // does nothing about aliases like `*LV1`)
-
-                            // FIXME: do I need to check validity of
-                            // `_r` here though? (I think the original
-                            // check_loans code did, like the readme
-                            // says)
-
-                            // (And do I *really* not have to
-                            // recursively process the `base` as a
-                            // further search here? Leaving this `if
-                            // false` here as a hint to look at this
-                            // again later.
-                            //
-                            // Ah, it might be because the
-                            // restrictions are distinct from the path
-                            // substructure. Note that there is a
-                            // separate loop over the path
-                            // substructure in fn
-                            // each_borrow_involving_path, for better
-                            // or for worse.
-
-                            if false {
-                                cursor = &proj.base;
-                                continue 'cursor;
-                            } else {
-                                continue 'pop;
-                            }
-                        }
-
-                        // R-Deref-Mut-Borrowed
-                        ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                            // mutably-borrowed referents are
-                            // themselves restricted.
-
-                            // FIXME: do I need to check validity of
-                            // `_r` here though? (I think the original
-                            // check_loans code did, like the readme
-                            // says)
-
-                            // schedule base for future iteration.
-                            self.lvalue_stack.push(&proj.base);
-                            return Some(cursor); // search yielded interior node
-                        }
+                assert_eq!(self.kind, PrefixSet::Supporting);
+                // supporting prefixes: strip away fields and
+                // derefs, except we stop at the deref of a shared
+                // reference.
+
+                let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                match ty.sty {
+                    ty::TyRawPtr(_) |
+                    ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+                        // don't continue traversing over derefs of raw pointers or shared borrows.
+                        self.next = None;
+                        return Some(cursor);
+                    }
 
-                        // R-Deref-Send-Pointer
-                        ty::TyAdt(..) if ty.is_box() => {
-                            // borrowing interior of a box implies that
-                            // its base can no longer be mutated (o/w box
-                            // storage would be freed)
-                            self.lvalue_stack.push(&proj.base);
-                            return Some(cursor); // search yielded interior node
-                        }
+                    ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+                        self.next = Some(&proj.base);
+                        return Some(cursor);
+                    }
 
-                        _ => panic!("unknown type fed to Projection Deref."),
+                    ty::TyAdt(..) if ty.is_box() => {
+                        self.next = Some(&proj.base);
+                        return Some(cursor);
                     }
+
+                    _ => panic!("unknown type fed to Projection Deref."),
                 }
             }
         }
@@ -895,71 +901,119 @@ mod restrictions {
 impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
     fn report_use_of_moved(&mut self,
                            _context: Context,
+                           desired_action: &str,
                            (lvalue, span): (&Lvalue, Span)) {
-        let mut err = self.tcx.cannot_act_on_uninitialized_variable(
-            span, "use", &self.describe_lvalue(lvalue), Origin::Mir);
-        // FIXME: add span_label for use of uninitialized variable
-        err.emit();
+        self.tcx.cannot_act_on_uninitialized_variable(span,
+                                                      desired_action,
+                                                      &self.describe_lvalue(lvalue),
+                                                      Origin::Mir)
+                .span_label(span, format!("use of possibly uninitialized `{}`",
+                                          self.describe_lvalue(lvalue)))
+                .emit();
     }
 
     fn report_move_out_while_borrowed(&mut self,
                                       _context: Context,
-                                      (lvalue, span): (&Lvalue, Span)) {
-        let mut err = self.tcx.cannot_move_when_borrowed(
-            span, &self.describe_lvalue(lvalue), Origin::Mir);
-        // FIXME 1: add span_label for "borrow of `()` occurs here"
-        // FIXME 2: add span_label for "move out of `{}` occurs here"
-        err.emit();
+                                      (lvalue, span): (&Lvalue, Span),
+                                      borrow: &BorrowData) {
+        self.tcx.cannot_move_when_borrowed(span,
+                                           &self.describe_lvalue(lvalue),
+                                           Origin::Mir)
+                .span_label(self.retrieve_borrow_span(borrow),
+                            format!("borrow of `{}` occurs here",
+                                    self.describe_lvalue(&borrow.lvalue)))
+                .span_label(span, format!("move out of `{}` occurs here",
+                                          self.describe_lvalue(lvalue)))
+                .emit();
     }
 
     fn report_use_while_mutably_borrowed(&mut self,
                                          _context: Context,
-                                         (lvalue, span): (&Lvalue, Span)) {
+                                         (lvalue, span): (&Lvalue, Span),
+                                         borrow : &BorrowData) {
+        let described_lvalue = self.describe_lvalue(lvalue);
+        let borrow_span = self.retrieve_borrow_span(borrow);
+
         let mut err = self.tcx.cannot_use_when_mutably_borrowed(
-            span, &self.describe_lvalue(lvalue), Origin::Mir);
-        // FIXME 1: add span_label for "borrow of `()` occurs here"
-        // FIXME 2: add span_label for "use of `{}` occurs here"
+            span, &described_lvalue, Origin::Mir);
+
+        err.span_label(borrow_span, format!("borrow of `{}` occurs here", described_lvalue));
+        err.span_label(span, format!("use of borrowed `{}`", described_lvalue));
+
         err.emit();
     }
 
     fn report_conflicting_borrow(&mut self,
                                  _context: Context,
                                  (lvalue, span): (&Lvalue, Span),
-                                 loan1: &BorrowData,
-                                 loan2: &BorrowData) {
+                                 loan1: (&Lvalue, BorrowKind),
+                                 loan2: (&Lvalue, BorrowKind)) {
+        let (loan1_lvalue, loan1_kind) = loan1;
+        let (loan2_lvalue, loan2_kind) = loan2;
         // FIXME: obviously falsifiable. Generalize for non-eq lvalues later.
-        assert_eq!(loan1.lvalue, loan2.lvalue);
+        assert_eq!(loan1_lvalue, loan2_lvalue);
 
         // FIXME: supply non-"" `opt_via` when appropriate
-        let mut err = match (loan1.kind, "immutable", "mutable",
-                             loan2.kind, "immutable", "mutable") {
+        let mut err = match (loan1_kind, "immutable", "mutable",
+                             loan2_kind, "immutable", "mutable") {
             (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
-            (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) |
-            (BorrowKind::Mut, _, lft, BorrowKind::Mut, _, rgt) =>
+            (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) =>
                 self.tcx.cannot_reborrow_already_borrowed(
                     span, &self.describe_lvalue(lvalue),
                     "", lft, "it", rgt, "", Origin::Mir),
 
-            _ =>  self.tcx.cannot_mutably_borrow_multiply(
-                span, &self.describe_lvalue(lvalue), "", Origin::Mir),
+            (BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) =>
+                self.tcx.cannot_mutably_borrow_multiply(
+                    span, &self.describe_lvalue(lvalue), "", Origin::Mir),
+
+            (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) =>
+                self.tcx.cannot_uniquely_borrow_by_two_closures(
+                    span, &self.describe_lvalue(lvalue), Origin::Mir),
+
+            (BorrowKind::Unique, _, _, _, _, _) =>
+                self.tcx.cannot_uniquely_borrow_by_one_closure(
+                    span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir),
+
+            (_, _, _, BorrowKind::Unique, _, _) =>
+                self.tcx.cannot_reborrow_already_uniquely_borrowed(
+                    span, &self.describe_lvalue(lvalue), "it", "", Origin::Mir),
+
+            (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) =>
+                unreachable!(),
+
             // FIXME: add span labels for first and second mutable borrows, as well as
             // end point for first.
         };
         err.emit();
     }
 
-    fn report_illegal_mutation_of_borrowed(&mut self, _: Context, (lvalue, span): (&Lvalue, Span)) {
+    fn report_illegal_mutation_of_borrowed(&mut self,
+                                           _: Context,
+                                           (lvalue, span): (&Lvalue, Span),
+                                           loan: &BorrowData) {
+        let describe_lvalue = self.describe_lvalue(lvalue);
+        let borrow_span = self.retrieve_borrow_span(loan);
+
         let mut err = self.tcx.cannot_assign_to_borrowed(
             span, &self.describe_lvalue(lvalue), Origin::Mir);
-        // FIXME: add span labels for borrow and assignment points
+
+        err.span_label(borrow_span, format!("borrow of `{}` occurs here", describe_lvalue));
+        err.span_label(span, format!("assignment to borrowed `{}` occurs here", describe_lvalue));
+
         err.emit();
     }
 
-    fn report_illegal_reassignment(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) {
-        let mut err = self.tcx.cannot_reassign_immutable(
-            span, &self.describe_lvalue(lvalue), Origin::Mir);
-        // FIXME: add span labels for borrow and assignment points
-        err.emit();
+    fn report_illegal_reassignment(&mut self,
+                                   _context: Context,
+                                   (lvalue, span): (&Lvalue, Span),
+                                   assigned_span: Span) {
+        self.tcx.cannot_reassign_immutable(span,
+                                           &self.describe_lvalue(lvalue),
+                                           Origin::Mir)
+                .span_label(span, "re-assignment of immutable variable")
+                .span_label(assigned_span, format!("first assignment to `{}`",
+                                                   self.describe_lvalue(lvalue)))
+                .emit();
     }
 
     fn report_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) {
@@ -998,7 +1052,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
                     ProjectionElem::Downcast(..) =>
                         ("",   format!(""), None), // (dont emit downcast info)
                     ProjectionElem::Field(field, _ty) =>
-                        ("",   format!(".{}", field.index()), None),
+                        ("",   format!(".{}", field.index()), None), // FIXME: report name of field
                     ProjectionElem::Index(index) =>
                         ("",   format!(""), Some(index)),
                     ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
@@ -1024,28 +1078,16 @@ 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> {
-    // FIXME: needs to be able to express errors analogous to check_loans.rs
-    fn conflicts_with(&self, loan1: &BorrowData<'gcx>, loan2: &BorrowData<'gcx>) -> bool {
-        if loan1.compatible_with(loan2.kind) { return false; }
-
-        let loan2_base_path = self.base_path(&loan2.lvalue);
-        for restricted in self.restrictions(&loan1.lvalue) {
-            if restricted != loan2_base_path { continue; }
-            return true;
-        }
-
-        let loan1_base_path = self.base_path(&loan1.lvalue);
-        for restricted in self.restrictions(&loan2.lvalue) {
-            if restricted != loan1_base_path { continue; }
-            return true;
-        }
-
-        return false;
+    // Retrieve span of given borrow from the current MIR representation
+    fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
+        self.mir.basic_blocks()[borrow.location.block]
+            .statements[borrow.location.statement_index]
+            .source_info.span
     }
+}
 
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
     // FIXME (#16118): function intended to allow the borrow checker
     // to be less precise in its handling of Box while still allowing
     // moves out of a Box. They should be removed when/if we stop
@@ -1092,8 +1134,8 @@ enum ContextKind {
     CallOperand,
     CallDest,
     Assert,
-    StorageDead,
     Yield,
+    StorageDead,
 }
 
 impl ContextKind {
@@ -1225,26 +1267,8 @@ impl<BD> FlowInProgress<BD> where BD: BitDenotation {
         self.curr_state.subtract(&self.stmt_kill);
     }
 
-    fn elems_generated(&self) -> indexed_set::Elems<BD::Idx> {
-        let univ = self.base_results.sets().bits_per_block();
-        self.stmt_gen.elems(univ)
-    }
-
     fn elems_incoming(&self) -> indexed_set::Elems<BD::Idx> {
         let univ = self.base_results.sets().bits_per_block();
         self.curr_state.elems(univ)
     }
 }
-
-impl<'tcx> BorrowData<'tcx> {
-    fn compatible_with(&self, bk: BorrowKind) -> bool {
-        match (self.kind, bk) {
-            (BorrowKind::Shared, BorrowKind::Shared) => true,
-
-            (BorrowKind::Mut, _) |
-            (BorrowKind::Unique, _) |
-            (_, BorrowKind::Mut) |
-            (_, BorrowKind::Unique) => false,
-        }
-    }
-}
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index 0e412fb27ca..1fc96dbf451 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -21,22 +21,32 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                      ast_block: &'tcx hir::Block,
                      source_info: SourceInfo)
                      -> BlockAnd<()> {
-        let Block { region_scope, opt_destruction_scope, span, stmts, expr, targeted_by_break } =
+        let Block {
+            region_scope,
+            opt_destruction_scope,
+            span,
+            stmts,
+            expr,
+            targeted_by_break,
+            safety_mode
+        } =
             self.hir.mirror(ast_block);
         self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
-            this.in_scope((region_scope, source_info), block, move |this| {
+            this.in_scope((region_scope, source_info), LintLevel::Inherited, block, move |this| {
                 if targeted_by_break {
                     // This is a `break`-able block (currently only `catch { ... }`)
                     let exit_block = this.cfg.start_new_block();
                     let block_exit = this.in_breakable_scope(
                         None, exit_block, destination.clone(), |this| {
-                            this.ast_block_stmts(destination, block, span, stmts, expr)
+                            this.ast_block_stmts(destination, block, span, stmts, expr,
+                                                 safety_mode)
                         });
                     this.cfg.terminate(unpack!(block_exit), source_info,
                                        TerminatorKind::Goto { target: exit_block });
                     exit_block.unit()
                 } else {
-                    this.ast_block_stmts(destination, block, span, stmts, expr)
+                    this.ast_block_stmts(destination, block, span, stmts, expr,
+                                         safety_mode)
                 }
             })
         })
@@ -47,7 +57,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                        mut block: BasicBlock,
                        span: Span,
                        stmts: Vec<StmtRef<'tcx>>,
-                       expr: Option<ExprRef<'tcx>>)
+                       expr: Option<ExprRef<'tcx>>,
+                       safety_mode: BlockSafety)
                        -> BlockAnd<()> {
         let this = self;
 
@@ -69,6 +80,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // First we build all the statements in the block.
         let mut let_scope_stack = Vec::with_capacity(8);
         let outer_visibility_scope = this.visibility_scope;
+        let outer_push_unsafe_count = this.push_unsafe_count;
+        let outer_unpushed_unsafe = this.unpushed_unsafe;
+        this.update_visibility_scope_for_safety_mode(span, safety_mode);
+
         let source_info = this.source_info(span);
         for stmt in stmts {
             let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
@@ -76,13 +91,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 StmtKind::Expr { scope, expr } => {
                     unpack!(block = this.in_opt_scope(
                         opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
-                            this.in_scope((scope, source_info), block, |this| {
+                            let si = (scope, source_info);
+                            this.in_scope(si, LintLevel::Inherited, block, |this| {
                                 let expr = this.hir.mirror(expr);
                                 this.stmt_expr(block, expr)
                             })
                         }));
                 }
-                StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
+                StmtKind::Let {
+                    remainder_scope,
+                    init_scope,
+                    pattern,
+                    initializer,
+                    lint_level
+                } => {
                     // Enter the remainder scope, i.e. the bindings' destruction scope.
                     this.push_scope((remainder_scope, source_info));
                     let_scope_stack.push(remainder_scope);
@@ -90,13 +112,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     // Declare the bindings, which may create a visibility scope.
                     let remainder_span = remainder_scope.span(this.hir.tcx(),
                                                               &this.hir.region_scope_tree);
-                    let scope = this.declare_bindings(None, remainder_span, &pattern);
+                    let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern);
 
                     // Evaluate the initializer, if present.
                     if let Some(init) = initializer {
                         unpack!(block = this.in_opt_scope(
                             opt_destruction_scope.map(|de|(de, source_info)), block, move |this| {
-                                this.in_scope((init_scope, source_info), block, move |this| {
+                                let scope = (init_scope, source_info);
+                                this.in_scope(scope, lint_level, block, move |this| {
                                     // FIXME #30046                             ^~~~
                                     this.expr_into_pattern(block, pattern, init)
                                 })
@@ -129,6 +152,48 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         }
         // Restore the original visibility scope.
         this.visibility_scope = outer_visibility_scope;
+        this.push_unsafe_count = outer_push_unsafe_count;
+        this.unpushed_unsafe = outer_unpushed_unsafe;
         block.unit()
     }
+
+    /// If we are changing the safety mode, create a new visibility scope
+    fn update_visibility_scope_for_safety_mode(&mut self,
+                                               span: Span,
+                                               safety_mode: BlockSafety)
+    {
+        debug!("update_visibility_scope_for({:?}, {:?})", span, safety_mode);
+        let new_unsafety = match safety_mode {
+            BlockSafety::Safe => None,
+            BlockSafety::ExplicitUnsafe(node_id) => {
+                assert_eq!(self.push_unsafe_count, 0);
+                match self.unpushed_unsafe {
+                    Safety::Safe => {}
+                    _ => return
+                }
+                self.unpushed_unsafe = Safety::ExplicitUnsafe(node_id);
+                Some(Safety::ExplicitUnsafe(node_id))
+            }
+            BlockSafety::PushUnsafe => {
+                self.push_unsafe_count += 1;
+                Some(Safety::BuiltinUnsafe)
+            }
+            BlockSafety::PopUnsafe => {
+                self.push_unsafe_count =
+                    self.push_unsafe_count.checked_sub(1).unwrap_or_else(|| {
+                        span_bug!(span, "unsafe count underflow")
+                    });
+                if self.push_unsafe_count == 0 {
+                    Some(self.unpushed_unsafe)
+                } else {
+                    None
+                }
+            }
+        };
+
+        if let Some(unsafety) = new_unsafety {
+            self.visibility_scope = self.new_visibility_scope(
+                span, LintLevel::Inherited, Some(unsafety));
+        }
+    }
 }
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs
index a86b7f4d239..a57f1b95494 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir/build/expr/as_constant.rs
@@ -29,7 +29,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let Expr { ty, temp_lifetime: _, span, kind }
             = expr;
         match kind {
-            ExprKind::Scope { region_scope: _, value } =>
+            ExprKind::Scope { region_scope: _, lint_level: _, value } =>
                 this.as_constant(value),
             ExprKind::Literal { literal } =>
                 Constant { span: span, ty: ty, literal: literal },
diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs
index 9cbaff2c113..69d0dd99228 100644
--- a/src/librustc_mir/build/expr/as_lvalue.rs
+++ b/src/librustc_mir/build/expr/as_lvalue.rs
@@ -39,8 +39,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
         match expr.kind {
-            ExprKind::Scope { region_scope, value } => {
-                this.in_scope((region_scope, source_info), block, |this| {
+            ExprKind::Scope { region_scope, lint_level, value } => {
+                this.in_scope((region_scope, source_info), lint_level, block, |this| {
                     this.as_lvalue(block, value)
                 })
             }
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs
index 0a72ce8d05e..ea6e4342098 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir/build/expr/as_operand.rs
@@ -55,10 +55,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
         let this = self;
 
-        if let ExprKind::Scope { region_scope, value } = expr.kind {
+        if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
             let source_info = this.source_info(expr.span);
             let region_scope = (region_scope, source_info);
-            return this.in_scope(region_scope, block, |this| {
+            return this.in_scope(region_scope, lint_level, block, |this| {
                 this.as_operand(block, scope, value)
             });
         }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index f2607b164de..d17f00b489c 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -58,9 +58,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let source_info = this.source_info(expr_span);
 
         match expr.kind {
-            ExprKind::Scope { region_scope, value } => {
+            ExprKind::Scope { region_scope, lint_level, value } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, block, |this| this.as_rvalue(block, scope, value))
+                this.in_scope(region_scope, lint_level, block,
+                              |this| this.as_rvalue(block, scope, value))
             }
             ExprKind::Repeat { value, count } => {
                 let value_operand = unpack!(block = this.as_operand(block, scope, value));
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 7826769600b..ba422a81831 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -41,8 +41,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
-        if let ExprKind::Scope { region_scope, value } = expr.kind {
-            return this.in_scope((region_scope, source_info), block, |this| {
+        if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
+            return this.in_scope((region_scope, source_info), lint_level, block, |this| {
                 this.as_temp(block, temp_lifetime, value)
             });
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index ec06e474980..cdbcb43370f 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -38,9 +38,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let source_info = this.source_info(expr_span);
 
         match expr.kind {
-            ExprKind::Scope { region_scope, value } => {
+            ExprKind::Scope { region_scope, lint_level, value } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, block, |this| this.into(destination, block, value))
+                this.in_scope(region_scope, lint_level, block,
+                              |this| this.into(destination, block, value))
             }
             ExprKind::Block { body: ast_block } => {
                 this.ast_block(destination, block, ast_block, source_info)
@@ -227,9 +228,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     let val = args.next().expect("1 argument to `move_val_init`");
                     assert!(args.next().is_none(), ">2 arguments to `move_val_init`");
 
-                    let topmost_scope = this.topmost_scope();
-                    let ptr = unpack!(block = this.as_temp(block, Some(topmost_scope), ptr));
-                    this.into(&Lvalue::Local(ptr).deref(), block, val)
+                    let ptr = this.hir.mirror(ptr);
+                    let ptr_ty = ptr.ty;
+                    // Create an *internal* temp for the pointer, so that unsafety
+                    // checking won't complain about the raw pointer assignment.
+                    let ptr_temp = this.local_decls.push(LocalDecl {
+                        mutability: Mutability::Mut,
+                        ty: ptr_ty,
+                        name: None,
+                        source_info,
+                        lexical_scope: source_info.scope,
+                        internal: true,
+                        is_user_variable: false
+                    });
+                    let ptr_temp = Lvalue::Local(ptr_temp);
+                    let block = unpack!(this.into(&ptr_temp, block, ptr));
+                    this.into(&ptr_temp.deref(), block, val)
                 } else {
                     let args: Vec<_> =
                         args.into_iter()
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index 84468d5d6dc..3cfb0ff4010 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -22,9 +22,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // Handle a number of expressions that don't need a destination at all. This
         // avoids needing a mountain of temporary `()` variables.
         match expr.kind {
-            ExprKind::Scope { region_scope, value } => {
+            ExprKind::Scope { region_scope, lint_level, value } => {
                 let value = this.hir.mirror(value);
-                this.in_scope((region_scope, source_info), block, |this| {
+                this.in_scope((region_scope, source_info), lint_level, block, |this| {
                     this.stmt_expr(block, value)
                 })
             }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index f560fa426e2..f04dede6e40 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -46,8 +46,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         // Get the arm bodies and their scopes, while declaring bindings.
         let arm_bodies: Vec<_> = arms.iter().map(|arm| {
+            // BUG: use arm lint level
             let body = self.hir.mirror(arm.body.clone());
-            let scope = self.declare_bindings(None, body.span, &arm.patterns[0]);
+            let scope = self.declare_bindings(None, body.span,
+                                              LintLevel::Inherited,
+                                              &arm.patterns[0]);
             (body, scope.unwrap_or(self.visibility_scope))
         }).collect();
 
@@ -171,11 +174,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn declare_bindings(&mut self,
                             mut var_scope: Option<VisibilityScope>,
                             scope_span: Span,
+                            lint_level: LintLevel,
                             pattern: &Pattern<'tcx>)
                             -> Option<VisibilityScope> {
+        assert!(!(var_scope.is_some() && lint_level.is_explicit()),
+               "can't have both a var and a lint scope at the same time");
         self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
             if var_scope.is_none() {
-                var_scope = Some(this.new_visibility_scope(scope_span));
+                var_scope = Some(this.new_visibility_scope(scope_span,
+                                                           LintLevel::Inherited,
+                                                           None));
+                // If we have lints, create a new visibility scope
+                // that marks the lints for the locals.
+                if lint_level.is_explicit() {
+                    this.visibility_scope =
+                        this.new_visibility_scope(scope_span, lint_level, None);
+                }
             }
             let source_info = SourceInfo {
                 span,
@@ -183,6 +197,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             };
             this.declare_binding(source_info, mutability, name, var, ty);
         });
+        // Pop any scope we created for the locals.
+        if let Some(var_scope) = var_scope {
+            self.visibility_scope = var_scope;
+        }
         var_scope
     }
 
@@ -712,6 +730,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ty: var_ty.clone(),
             name: Some(name),
             source_info,
+            lexical_scope: self.visibility_scope,
             internal: false,
             is_user_variable: true,
         });
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index be6f8c9e56c..68ef646184c 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -11,6 +11,7 @@
 
 use build;
 use hair::cx::Cx;
+use hair::LintLevel;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
@@ -71,14 +72,14 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             // is a constant "initializer" expression.
             match expr.node {
                 hir::ExprClosure(_, _, body, _, _) => body,
-                _ => hir::BodyId { node_id: expr.id }
+                _ => hir::BodyId { node_id: expr.id },
             }
         }
         hir::map::NodeVariant(variant) =>
             return create_constructor_shim(tcx, id, &variant.node.data),
         hir::map::NodeStructCtor(ctor) =>
             return create_constructor_shim(tcx, id, ctor),
-        _ => unsupported()
+        _ => unsupported(),
     };
 
     let src = MirSource::from_node(tcx, id);
@@ -108,6 +109,12 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
                 _ => None,
             };
 
+            // FIXME: safety in closures
+            let safety = match fn_sig.unsafety {
+                hir::Unsafety::Normal => Safety::Safe,
+                hir::Unsafety::Unsafe => Safety::FnUnsafe,
+            };
+
             let body = tcx.hir.body(body_id);
             let explicit_arguments =
                 body.arguments
@@ -126,7 +133,8 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
                 (None, fn_sig.output())
             };
 
-            build::construct_fn(cx, id, arguments, abi, return_ty, yield_ty, body)
+            build::construct_fn(cx, id, arguments, safety, abi,
+                                return_ty, yield_ty, body)
         } else {
             build::construct_const(cx, body_id)
         };
@@ -270,6 +278,13 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// see the `scope` module for more details
     scopes: Vec<scope::Scope<'tcx>>,
 
+    /// The current unsafe block in scope, even if it is hidden by
+    /// a PushUnsafeBlock
+    unpushed_unsafe: Safety,
+
+    /// The number of `push_unsafe_block` levels in scope
+    push_unsafe_count: usize,
+
     /// the current set of breakables; see the `scope` module for more
     /// details
     breakable_scopes: Vec<scope::BreakableScope<'tcx>>,
@@ -277,6 +292,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// the vector of all scopes that we have created thus far;
     /// we track this for debuginfo later
     visibility_scopes: IndexVec<VisibilityScope, VisibilityScopeData>,
+    visibility_scope_info: IndexVec<VisibilityScope, VisibilityScopeInfo>,
     visibility_scope: VisibilityScope,
 
     /// Maps node ids of variable bindings to the `Local`s created for them.
@@ -358,6 +374,7 @@ macro_rules! unpack {
 fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    fn_id: ast::NodeId,
                                    arguments: A,
+                                   safety: Safety,
                                    abi: Abi,
                                    return_ty: Ty<'gcx>,
                                    yield_ty: Option<Ty<'gcx>>,
@@ -372,14 +389,17 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
     let mut builder = Builder::new(hir.clone(),
         span,
         arguments.len(),
+        safety,
         return_ty);
 
     let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id);
     let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
     let mut block = START_BLOCK;
     let source_info = builder.source_info(span);
-    unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| {
-        unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| {
+    let call_site_s = (call_site_scope, source_info);
+    unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| {
+        let arg_scope_s = (arg_scope, source_info);
+        unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| {
             builder.args_and_body(block, &arguments, arg_scope, &body.value)
         }));
         // Attribute epilogue to function's closing brace
@@ -440,7 +460,7 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
     let ty = hir.tables().expr_ty_adjusted(ast_expr);
     let owner_id = tcx.hir.body_owner(body_id);
     let span = tcx.hir.span(owner_id);
-    let mut builder = Builder::new(hir.clone(), span, 0, ty);
+    let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty);
 
     let mut block = START_BLOCK;
     let expr = builder.hir.mirror(ast_expr);
@@ -456,11 +476,12 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
 }
 
 fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
-                                       body_id: hir::BodyId)
-                                       -> Mir<'tcx> {
-    let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
+                                   body_id: hir::BodyId)
+                                   -> Mir<'tcx> {
+    let owner_id = hir.tcx().hir.body_owner(body_id);
+    let span = hir.tcx().hir.span(owner_id);
     let ty = hir.tcx().types.err;
-    let mut builder = Builder::new(hir, span, 0, ty);
+    let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty);
     let source_info = builder.source_info(span);
     builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
     builder.finish(vec![], ty, None)
@@ -470,8 +491,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     fn new(hir: Cx<'a, 'gcx, 'tcx>,
            span: Span,
            arg_count: usize,
+           safety: Safety,
            return_ty: Ty<'tcx>)
            -> Builder<'a, 'gcx, 'tcx> {
+        let lint_level = LintLevel::Explicit(hir.root_lint_level);
         let mut builder = Builder {
             hir,
             cfg: CFG { basic_blocks: IndexVec::new() },
@@ -480,6 +503,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             scopes: vec![],
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
+            visibility_scope_info: IndexVec::new(),
+            push_unsafe_count: 0,
+            unpushed_unsafe: safety,
             breakable_scopes: vec![],
             local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty,
                                                                              span), 1),
@@ -490,7 +516,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         };
 
         assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
-        assert_eq!(builder.new_visibility_scope(span), ARGUMENT_VISIBILITY_SCOPE);
+        assert_eq!(
+            builder.new_visibility_scope(span, lint_level, Some(safety)),
+            ARGUMENT_VISIBILITY_SCOPE);
         builder.visibility_scopes[ARGUMENT_VISIBILITY_SCOPE].parent_scope = None;
 
         builder
@@ -509,6 +537,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         Mir::new(self.cfg.basic_blocks,
                  self.visibility_scopes,
+                 ClearOnDecode::Set(self.visibility_scope_info),
                  IndexVec::new(),
                  return_ty,
                  yield_ty,
@@ -543,6 +572,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     scope: ARGUMENT_VISIBILITY_SCOPE,
                     span: pattern.map_or(self.fn_span, |pat| pat.span)
                 },
+                lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
                 name,
                 internal: false,
                 is_user_variable: false,
@@ -557,7 +587,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
             if let Some(pattern) = pattern {
                 let pattern = self.hir.pattern_from_hir(pattern);
-                scope = self.declare_bindings(scope, ast_body.span, &pattern);
+                scope = self.declare_bindings(scope, ast_body.span,
+                                              LintLevel::Inherited, &pattern);
                 unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
             }
 
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index bac884b4d01..03273419432 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -88,8 +88,10 @@ should go to.
 */
 
 use build::{BlockAnd, BlockAndExtension, Builder, CFG};
+use hair::LintLevel;
 use rustc::middle::region;
 use rustc::ty::{Ty, TyCtxt};
+use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 use syntax_pos::{Span};
@@ -304,15 +306,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// to build its contents, popping the scope afterwards.
     pub fn in_scope<F, R>(&mut self,
                           region_scope: (region::Scope, SourceInfo),
+                          lint_level: LintLevel,
                           mut block: BasicBlock,
                           f: F)
                           -> BlockAnd<R>
         where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
     {
         debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block);
+        let visibility_scope = self.visibility_scope;
+        let tcx = self.hir.tcx();
+        if let LintLevel::Explicit(node_id) = lint_level {
+            let same_lint_scopes = tcx.dep_graph.with_ignore(|| {
+                let sets = tcx.lint_levels(LOCAL_CRATE);
+                let parent_hir_id =
+                    tcx.hir.definitions().node_to_hir_id(
+                        self.visibility_scope_info[visibility_scope].lint_root
+                            );
+                let current_hir_id =
+                    tcx.hir.definitions().node_to_hir_id(node_id);
+                sets.lint_level_set(parent_hir_id) ==
+                    sets.lint_level_set(current_hir_id)
+            });
+
+            if !same_lint_scopes {
+                self.visibility_scope =
+                    self.new_visibility_scope(region_scope.1.span, lint_level,
+                                              None);
+            }
+        }
         self.push_scope(region_scope);
         let rv = unpack!(block = f(self));
         unpack!(block = self.pop_scope(region_scope, block));
+        self.visibility_scope = visibility_scope;
         debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
         block.and(rv)
     }
@@ -474,13 +499,29 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     }
 
     /// Creates a new visibility scope, nested in the current one.
-    pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
+    pub fn new_visibility_scope(&mut self,
+                                span: Span,
+                                lint_level: LintLevel,
+                                safety: Option<Safety>) -> VisibilityScope {
         let parent = self.visibility_scope;
-        let scope = VisibilityScope::new(self.visibility_scopes.len());
-        self.visibility_scopes.push(VisibilityScopeData {
+        debug!("new_visibility_scope({:?}, {:?}, {:?}) - parent({:?})={:?}",
+               span, lint_level, safety,
+               parent, self.visibility_scope_info.get(parent));
+        let scope = self.visibility_scopes.push(VisibilityScopeData {
             span,
             parent_scope: Some(parent),
         });
+        let scope_info = VisibilityScopeInfo {
+            lint_root: if let LintLevel::Explicit(lint_root) = lint_level {
+                lint_root
+            } else {
+                self.visibility_scope_info[parent].lint_root
+            },
+            safety: safety.unwrap_or_else(|| {
+                self.visibility_scope_info[parent].safety
+            })
+        };
+        self.visibility_scope_info.push(scope_info);
         scope
     }
 
@@ -514,8 +555,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
         // We want `scopes[1]`, which is the `ParameterScope`.
         assert!(self.scopes.len() >= 2);
-        assert!(match self.scopes[1].region_scope {
-            region::Scope::Arguments(_) => true,
+        assert!(match self.scopes[1].region_scope.data() {
+            region::ScopeData::Arguments(_) => true,
             _ => false,
         });
         self.scopes[1].region_scope
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 26436d54ac8..2c4afb0aa0e 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -195,6 +195,40 @@ instead of using a `const fn`, or refactoring the code to a functional style to
 avoid mutation if possible.
 "##,
 
+E0133: r##"
+Unsafe code was used outside of an unsafe function or block.
+
+Erroneous code example:
+
+```compile_fail,E0133
+unsafe fn f() { return; } // This is the unsafe code
+
+fn main() {
+    f(); // error: call to unsafe function requires unsafe function or block
+}
+```
+
+Using unsafe functionality is potentially dangerous and disallowed by safety
+checks. Examples:
+
+* Dereferencing raw pointers
+* Calling functions via FFI
+* Calling functions marked unsafe
+
+These safety checks can be relaxed for a section of the code by wrapping the
+unsafe instructions with an `unsafe` block. For instance:
+
+```
+unsafe fn f() { return; }
+
+fn main() {
+    unsafe { f(); } // ok!
+}
+```
+
+See also https://doc.rust-lang.org/book/first-edition/unsafe.html
+"##,
+
 E0381: r##"
 It is not allowed to use or capture an uninitialized variable. For example:
 
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index f6b847d6d6d..6f6258f52f7 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -14,6 +14,8 @@ use hair::cx::to_ref::ToRef;
 use rustc::middle::region::{self, BlockRemainder};
 use rustc::hir;
 
+use rustc_data_structures::indexed_vec::Idx;
+
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
     type Output = Block<'tcx>;
 
@@ -30,6 +32,16 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
             span: self.span,
             stmts,
             expr: self.expr.to_ref(),
+            safety_mode: match self.rules {
+                hir::BlockCheckMode::DefaultBlock =>
+                    BlockSafety::Safe,
+                hir::BlockCheckMode::UnsafeBlock(..) =>
+                    BlockSafety::ExplicitUnsafe(self.id),
+                hir::BlockCheckMode::PushUnsafeBlock(..) =>
+                    BlockSafety::PushUnsafe,
+                hir::BlockCheckMode::PopUnsafeBlock(..) =>
+                    BlockSafety::PopUnsafe
+            },
         }
     }
 }
@@ -61,7 +73,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     hir::DeclLocal(ref local) => {
                         let remainder_scope = region::Scope::Remainder(BlockRemainder {
                             block: block_id,
-                            first_statement_index: index as u32,
+                            first_statement_index: region::FirstStatementIndex::new(index),
                         });
 
                         let pattern = cx.pattern_from_hir(&local.pat);
@@ -71,6 +83,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 init_scope: region::Scope::Node(hir_id.local_id),
                                 pattern,
                                 initializer: local.init.to_ref(),
+                                lint_level: cx.lint_level_of(local.id),
                             },
                             opt_destruction_scope: opt_dxn_ext,
                         })));
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 45449103c80..f5a53e2aa8e 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -48,22 +48,24 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             kind: ExprKind::Scope {
                 region_scope: expr_scope,
                 value: expr.to_ref(),
+                lint_level: cx.lint_level_of(self.id),
             },
         };
 
         // Finally, create a destruction scope, if any.
         if let Some(region_scope) =
-                cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
-            expr = Expr {
-                temp_lifetime,
-                ty: expr.ty,
-                span: self.span,
-                kind: ExprKind::Scope {
-                    region_scope,
-                    value: expr.to_ref(),
-                },
-            };
-        }
+            cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) {
+                expr = Expr {
+                    temp_lifetime,
+                    ty: expr.ty,
+                    span: self.span,
+                    kind: ExprKind::Scope {
+                        region_scope,
+                        value: expr.to_ref(),
+                        lint_level: LintLevel::Inherited,
+                    },
+                };
+            }
 
         // OK, all done!
         expr
@@ -619,6 +621,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm)
         patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
         guard: arm.guard.to_ref(),
         body: arm.body.to_ref(),
+        // BUG: fix this
+        lint_level: LintLevel::Inherited,
     }
 }
 
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index f5e15979006..4434df0ac3e 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -20,13 +20,14 @@ use rustc::mir::transform::MirSource;
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
 use rustc_const_eval::ConstContext;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::region;
 use rustc::infer::InferCtxt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
+use syntax::ast;
 use syntax::symbol::Symbol;
 use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -37,6 +38,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
 
+    pub root_lint_level: ast::NodeId,
     pub param_env: ty::ParamEnv<'gcx>,
 
     /// Identity `Substs` for use with const-evaluation.
@@ -57,7 +59,8 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+               src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
         let constness = match src {
             MirSource::Const(_) |
             MirSource::Static(..) => hir::Constness::Const,
@@ -87,9 +90,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         // Constants and const fn's always need overflow checks.
         check_overflow |= constness == hir::Constness::Const;
 
+        let lint_level = lint_level_for_hir_id(tcx, src_id);
         Cx {
             tcx,
             infcx,
+            root_lint_level: lint_level,
             param_env: tcx.param_env(src_def_id),
             identity_substs: Substs::identity_for_item(tcx.global_tcx(), src_def_id),
             region_scope_tree: tcx.region_scope_tree(src_def_id),
@@ -99,6 +104,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
             check_overflow,
         }
     }
+
 }
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
@@ -229,6 +235,19 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         ty.needs_drop(self.tcx.global_tcx(), param_env)
     }
 
+    fn lint_level_of(&self, node_id: ast::NodeId) -> LintLevel {
+        let hir_id = self.tcx.hir.definitions().node_to_hir_id(node_id);
+        let has_lint_level = self.tcx.dep_graph.with_ignore(|| {
+            self.tcx.lint_levels(LOCAL_CRATE).lint_level_set(hir_id).is_some()
+        });
+
+        if has_lint_level {
+            LintLevel::Explicit(node_id)
+        } else {
+            LintLevel::Inherited
+        }
+    }
+
     pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.tcx
     }
@@ -242,6 +261,31 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
     }
 }
 
+fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
+    // Right now we insert a `with_ignore` node in the dep graph here to
+    // ignore the fact that `lint_levels` below depends on the entire crate.
+    // For now this'll prevent false positives of recompiling too much when
+    // anything changes.
+    //
+    // Once red/green incremental compilation lands we should be able to
+    // remove this because while the crate changes often the lint level map
+    // will change rarely.
+    tcx.dep_graph.with_ignore(|| {
+        let sets = tcx.lint_levels(LOCAL_CRATE);
+        loop {
+            let hir_id = tcx.hir.definitions().node_to_hir_id(id);
+            if sets.lint_level_set(hir_id).is_some() {
+                return id
+            }
+            let next = tcx.hir.get_parent_node(id);
+            if next == id {
+                bug!("lint traversal reached the root of the crate");
+            }
+            id = next;
+        }
+    })
+}
+
 mod block;
 mod expr;
 mod to_ref;
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 3162242de66..09a31f9ab8f 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -29,6 +29,21 @@ pub mod cx;
 
 pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
 
+#[derive(Copy, Clone, Debug)]
+pub enum LintLevel {
+    Inherited,
+    Explicit(ast::NodeId)
+}
+
+impl LintLevel {
+    pub fn is_explicit(self) -> bool {
+        match self {
+            LintLevel::Inherited => false,
+            LintLevel::Explicit(_) => true
+        }
+    }
+}
+
 #[derive(Clone, Debug)]
 pub struct Block<'tcx> {
     pub targeted_by_break: bool,
@@ -37,6 +52,15 @@ pub struct Block<'tcx> {
     pub span: Span,
     pub stmts: Vec<StmtRef<'tcx>>,
     pub expr: Option<ExprRef<'tcx>>,
+    pub safety_mode: BlockSafety,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum BlockSafety {
+    Safe,
+    ExplicitUnsafe(ast::NodeId),
+    PushUnsafe,
+    PopUnsafe
 }
 
 #[derive(Clone, Debug)]
@@ -73,7 +97,10 @@ pub enum StmtKind<'tcx> {
         pattern: Pattern<'tcx>,
 
         /// let pat = <INIT> ...
-        initializer: Option<ExprRef<'tcx>>
+        initializer: Option<ExprRef<'tcx>>,
+
+        /// the lint level for this let-statement
+        lint_level: LintLevel,
     },
 }
 
@@ -111,6 +138,7 @@ pub struct Expr<'tcx> {
 pub enum ExprKind<'tcx> {
     Scope {
         region_scope: region::Scope,
+        lint_level: LintLevel,
         value: ExprRef<'tcx>,
     },
     Box {
@@ -275,6 +303,7 @@ pub struct Arm<'tcx> {
     pub patterns: Vec<Pattern<'tcx>>,
     pub guard: Option<ExprRef<'tcx>>,
     pub body: ExprRef<'tcx>,
+    pub lint_level: LintLevel,
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 31480457723..a3a986918a4 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -140,6 +140,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
     LocalDecl {
         mutability, ty, name: None,
         source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span },
+        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false
     }
@@ -195,6 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         IndexVec::from_elem_n(
             VisibilityScopeData { span: span, parent_scope: None }, 1
         ),
+        ClearOnDecode::Clear,
         IndexVec::new(),
         sig.output(),
         None,
@@ -342,6 +344,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
             IndexVec::from_elem_n(
                 VisibilityScopeData { span: self.span, parent_scope: None }, 1
             ),
+            ClearOnDecode::Clear,
             IndexVec::new(),
             self.sig.output(),
             None,
@@ -804,6 +807,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         IndexVec::from_elem_n(
             VisibilityScopeData { span: span, parent_scope: None }, 1
         ),
+        ClearOnDecode::Clear,
         IndexVec::new(),
         sig.output(),
         None,
@@ -876,6 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         IndexVec::from_elem_n(
             VisibilityScopeData { span: span, parent_scope: None }, 1
         ),
+        ClearOnDecode::Clear,
         IndexVec::new(),
         sig.output(),
         None,
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
new file mode 100644
index 00000000000..49ce3622399
--- /dev/null
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -0,0 +1,387 @@
+// 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::fx::FxHashSet;
+use rustc_data_structures::indexed_vec::IndexVec;
+
+use rustc::ty::maps::Providers;
+use rustc::ty::{self, TyCtxt};
+use rustc::hir;
+use rustc::hir::def::Def;
+use rustc::hir::def_id::DefId;
+use rustc::hir::map::{DefPathData, Node};
+use rustc::lint::builtin::{SAFE_EXTERN_STATICS, UNUSED_UNSAFE};
+use rustc::mir::*;
+use rustc::mir::visit::{LvalueContext, Visitor};
+
+use syntax::ast;
+
+use std::rc::Rc;
+
+
+pub struct UnsafetyChecker<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+    visibility_scope_info: &'a IndexVec<VisibilityScope, VisibilityScopeInfo>,
+    violations: Vec<UnsafetyViolation>,
+    source_info: SourceInfo,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    used_unsafe: FxHashSet<ast::NodeId>,
+}
+
+impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
+    fn new(mir: &'a Mir<'tcx>,
+           visibility_scope_info: &'a IndexVec<VisibilityScope, VisibilityScopeInfo>,
+           tcx: TyCtxt<'a, 'tcx, 'tcx>,
+           param_env: ty::ParamEnv<'tcx>) -> Self {
+        Self {
+            mir,
+            visibility_scope_info,
+            violations: vec![],
+            source_info: SourceInfo {
+                span: mir.span,
+                scope: ARGUMENT_VISIBILITY_SCOPE
+            },
+            tcx,
+            param_env,
+            used_unsafe: FxHashSet(),
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
+    fn visit_terminator(&mut self,
+                        block: BasicBlock,
+                        terminator: &Terminator<'tcx>,
+                        location: Location)
+    {
+        self.source_info = terminator.source_info;
+        match terminator.kind {
+            TerminatorKind::Goto { .. } |
+            TerminatorKind::SwitchInt { .. } |
+            TerminatorKind::Drop { .. } |
+            TerminatorKind::Yield { .. } |
+            TerminatorKind::Assert { .. } |
+            TerminatorKind::DropAndReplace { .. } |
+            TerminatorKind::GeneratorDrop |
+            TerminatorKind::Resume |
+            TerminatorKind::Return |
+            TerminatorKind::Unreachable => {
+                                // safe (at least as emitted during MIR construction)
+            }
+
+            TerminatorKind::Call { ref func, .. } => {
+                let func_ty = func.ty(self.mir, self.tcx);
+                let sig = func_ty.fn_sig(self.tcx);
+                if let hir::Unsafety::Unsafe = sig.unsafety() {
+                    self.require_unsafe("call to unsafe function")
+                }
+            }
+        }
+        self.super_terminator(block, terminator, location);
+    }
+
+    fn visit_statement(&mut self,
+                       block: BasicBlock,
+                       statement: &Statement<'tcx>,
+                       location: Location)
+    {
+        self.source_info = statement.source_info;
+        match statement.kind {
+            StatementKind::Assign(..) |
+            StatementKind::SetDiscriminant { .. } |
+            StatementKind::StorageLive(..) |
+            StatementKind::StorageDead(..) |
+            StatementKind::EndRegion(..) |
+            StatementKind::Validate(..) |
+            StatementKind::Nop => {
+                // safe (at least as emitted during MIR construction)
+            }
+
+            StatementKind::InlineAsm { .. } => {
+                self.require_unsafe("use of inline assembly")
+            },
+        }
+        self.super_statement(block, statement, location);
+    }
+
+    fn visit_rvalue(&mut self,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location)
+    {
+        if let &Rvalue::Aggregate(
+            box AggregateKind::Closure(def_id, _),
+            _
+        ) = rvalue {
+            let unsafety_violations = self.tcx.unsafety_violations(def_id);
+            self.register_violations(&unsafety_violations);
+        }
+        self.super_rvalue(rvalue, location);
+    }
+
+    fn visit_lvalue(&mut self,
+                    lvalue: &Lvalue<'tcx>,
+                    context: LvalueContext<'tcx>,
+                    location: Location) {
+        match lvalue {
+            &Lvalue::Projection(box Projection {
+                ref base, ref elem
+            }) => {
+                let old_source_info = self.source_info;
+                if let &Lvalue::Local(local) = base {
+                    if self.mir.local_decls[local].internal {
+                        // Internal locals are used in the `move_val_init` desugaring.
+                        // We want to check unsafety against the source info of the
+                        // desugaring, rather than the source info of the RHS.
+                        self.source_info = self.mir.local_decls[local].source_info;
+                    }
+                }
+                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
+                match base_ty.sty {
+                    ty::TyRawPtr(..) => {
+                        self.require_unsafe("dereference of raw pointer")
+                    }
+                    ty::TyAdt(adt, _) if adt.is_union() => {
+                        if context == LvalueContext::Store ||
+                            context == LvalueContext::Drop
+                        {
+                            let elem_ty = match elem {
+                                &ProjectionElem::Field(_, ty) => ty,
+                                _ => span_bug!(
+                                    self.source_info.span,
+                                    "non-field projection {:?} from union?",
+                                    lvalue)
+                            };
+                            if elem_ty.moves_by_default(self.tcx, self.param_env,
+                                                        self.source_info.span) {
+                                self.require_unsafe(
+                                    "assignment to non-`Copy` union field")
+                            } else {
+                                // write to non-move union, safe
+                            }
+                        } else {
+                            self.require_unsafe("access to union field")
+                        }
+                    }
+                    _ => {}
+                }
+                self.source_info = old_source_info;
+            }
+            &Lvalue::Local(..) => {
+                // locals are safe
+            }
+            &Lvalue::Static(box Static { def_id, ty: _ }) => {
+                if self.is_static_mut(def_id) {
+                    self.require_unsafe("use of mutable static");
+                } else if self.tcx.is_foreign_item(def_id) {
+                    let source_info = self.source_info;
+                    let lint_root =
+                        self.visibility_scope_info[source_info.scope].lint_root;
+                    self.register_violations(&[UnsafetyViolation {
+                        source_info,
+                        description: "use of extern static",
+                        lint_node_id: Some(lint_root)
+                    }]);
+                }
+            }
+        }
+        self.super_lvalue(lvalue, context, location);
+    }
+}
+
+impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
+    fn is_static_mut(&self, def_id: DefId) -> bool {
+        if let Some(node) = self.tcx.hir.get_if_local(def_id) {
+            match node {
+                Node::NodeItem(&hir::Item {
+                    node: hir::ItemStatic(_, hir::MutMutable, _), ..
+                }) => true,
+                Node::NodeForeignItem(&hir::ForeignItem {
+                    node: hir::ForeignItemStatic(_, mutbl), ..
+                }) => mutbl,
+                _ => false
+            }
+        } else {
+            match self.tcx.describe_def(def_id) {
+                Some(Def::Static(_, mutbl)) => mutbl,
+                _ => false
+            }
+        }
+    }
+    fn require_unsafe(&mut self,
+                      description: &'static str)
+    {
+        let source_info = self.source_info;
+        self.register_violations(&[UnsafetyViolation {
+            source_info, description, lint_node_id: None
+        }]);
+    }
+
+    fn register_violations(&mut self, violations: &[UnsafetyViolation]) {
+        match self.visibility_scope_info[self.source_info.scope].safety {
+            Safety::Safe => {
+                for violation in violations {
+                    if !self.violations.contains(violation) {
+                        self.violations.push(violation.clone())
+                    }
+                }
+            }
+            Safety::BuiltinUnsafe | Safety::FnUnsafe => {}
+            Safety::ExplicitUnsafe(node_id) => {
+                if !violations.is_empty() {
+                    self.used_unsafe.insert(node_id);
+                }
+            }
+        }
+    }
+}
+
+pub(crate) fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        unsafety_violations,
+        ..*providers
+    };
+}
+
+struct UnusedUnsafeVisitor<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    used_unsafe: FxHashSet<ast::NodeId>
+}
+
+impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) ->
+        hir::intravisit::NestedVisitorMap<'this, 'tcx>
+    {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_block(&mut self, block: &'tcx hir::Block) {
+        hir::intravisit::walk_block(self, block);
+
+        if let hir::UnsafeBlock(hir::UserProvided) = block.rules {
+            if !self.used_unsafe.contains(&block.id) {
+                self.report_unused_unsafe(block);
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> UnusedUnsafeVisitor<'a, 'tcx> {
+    /// Return the NodeId for an enclosing scope that is also `unsafe`
+    fn is_enclosed(&self, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
+        let parent_id = self.tcx.hir.get_parent_node(id);
+        if parent_id != id {
+            if self.used_unsafe.contains(&parent_id) {
+                Some(("block".to_string(), parent_id))
+            } else if let Some(hir::map::NodeItem(&hir::Item {
+                node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+                ..
+            })) = self.tcx.hir.find(parent_id) {
+                Some(("fn".to_string(), parent_id))
+            } else {
+                self.is_enclosed(parent_id)
+            }
+        } else {
+            None
+        }
+    }
+
+    fn report_unused_unsafe(&self, block: &'tcx hir::Block) {
+        let mut db = self.tcx.struct_span_lint_node(UNUSED_UNSAFE,
+                                                    block.id,
+                                                    block.span,
+                                                    "unnecessary `unsafe` block");
+        db.span_label(block.span, "unnecessary `unsafe` block");
+        if let Some((kind, id)) = self.is_enclosed(block.id) {
+            db.span_note(self.tcx.hir.span(id),
+                         &format!("because it's nested under this `unsafe` {}", kind));
+        }
+        db.emit();
+    }
+}
+
+fn check_unused_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 def_id: DefId,
+                                 used_unsafe: FxHashSet<ast::NodeId>)
+{
+    let body_id =
+        tcx.hir.as_local_node_id(def_id).and_then(|node_id| {
+            tcx.hir.maybe_body_owned_by(node_id)
+        });
+
+    let body_id = match body_id {
+        Some(body) => body,
+        None => {
+            debug!("check_unused_unsafe({:?}) - no body found", def_id);
+            return
+        }
+    };
+    let body = tcx.hir.body(body_id);
+    debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})",
+           def_id, body, used_unsafe);
+
+    hir::intravisit::Visitor::visit_body(
+        &mut UnusedUnsafeVisitor { tcx, used_unsafe },
+        body);
+}
+
+fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) ->
+    Rc<[UnsafetyViolation]>
+{
+    debug!("unsafety_violations({:?})", def_id);
+
+    // NB: this borrow is valid because all the consumers of
+    // `mir_const` force this.
+    let mir = &tcx.mir_const(def_id).borrow();
+
+    let visibility_scope_info = match mir.visibility_scope_info {
+        ClearOnDecode::Set(ref data) => data,
+        ClearOnDecode::Clear => {
+            debug!("unsafety_violations: {:?} - remote, skipping", def_id);
+            return Rc::new([])
+        }
+    };
+
+    let param_env = tcx.param_env(def_id);
+    let mut checker = UnsafetyChecker::new(
+        mir, visibility_scope_info, tcx, param_env);
+    checker.visit_mir(mir);
+
+    check_unused_unsafe(tcx, def_id, checker.used_unsafe);
+    checker.violations.into()
+}
+
+pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    debug!("check_unsafety({:?})", def_id);
+    match tcx.def_key(def_id).disambiguated_data.data {
+        // closures are handled by their parent fn.
+        DefPathData::ClosureExpr => return,
+        _ => {}
+    };
+
+    for &UnsafetyViolation {
+        source_info, description, lint_node_id
+    } in &*tcx.unsafety_violations(def_id) {
+        // Report an error.
+        if let Some(lint_node_id) = lint_node_id {
+            tcx.lint_node(SAFE_EXTERN_STATICS,
+                          lint_node_id,
+                          source_info.span,
+                          &format!("{} requires unsafe function or \
+                                    block (error E0133)", description));
+        } else {
+            struct_span_err!(
+                tcx.sess, source_info.span, E0133,
+                "{} requires unsafe function or block", description)
+                .span_label(source_info.span, description)
+                .emit();
+        }
+    }
+}
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 78fe7b26ebf..729fe46ef37 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -301,6 +301,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
         ty: ret_ty,
         name: None,
         source_info: source_info(mir),
+        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -443,14 +444,15 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            mir: &mut Mir<'tcx>,
                            cases: Vec<(u32, BasicBlock)>,
-                           transform: &TransformVisitor<'a, 'tcx>) {
-    let return_block = insert_return_block(mir);
+                           transform: &TransformVisitor<'a, 'tcx>,
+                           default: TerminatorKind<'tcx>) {
+    let default_block = insert_term_block(mir, default);
 
     let switch = TerminatorKind::SwitchInt {
         discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)),
         switch_ty: tcx.types.u32,
         values: Cow::from(cases.iter().map(|&(i, _)| ConstInt::U32(i)).collect::<Vec<_>>()),
-        targets: cases.iter().map(|&(_, d)| d).chain(once(return_block)).collect(),
+        targets: cases.iter().map(|&(_, d)| d).chain(once(default_block)).collect(),
     };
 
     let source_info = source_info(mir);
@@ -542,7 +544,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
     // The returned state (1) and the poisoned state (2) falls through to
     // the default case which is just to return
 
-    insert_switch(tcx, &mut mir, cases, &transform);
+    insert_switch(tcx, &mut mir, cases, &transform, TerminatorKind::Return);
 
     for block in mir.basic_blocks_mut() {
         let kind = &mut block.terminator_mut().kind;
@@ -558,6 +560,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         ty: tcx.mk_nil(),
         name: None,
         source_info,
+        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -573,6 +576,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         }),
         name: None,
         source_info,
+        lexical_scope: ARGUMENT_VISIBILITY_SCOPE,
         internal: false,
         is_user_variable: false,
     };
@@ -588,18 +592,18 @@ fn create_generator_drop_shim<'a, 'tcx>(
     mir
 }
 
-fn insert_return_block<'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
-    let return_block = BasicBlock::new(mir.basic_blocks().len());
+fn insert_term_block<'tcx>(mir: &mut Mir<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock {
+    let term_block = BasicBlock::new(mir.basic_blocks().len());
     let source_info = source_info(mir);
     mir.basic_blocks_mut().push(BasicBlockData {
         statements: Vec::new(),
         terminator: Some(Terminator {
             source_info,
-            kind: TerminatorKind::Return,
+            kind,
         }),
         is_cleanup: false,
     });
-    return_block
+    term_block
 }
 
 fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -659,7 +663,7 @@ fn create_generator_resume_function<'a, 'tcx>(
     // Panic when resumed on the poisoned (2) state
     cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic)));
 
-    insert_switch(tcx, mir, cases, &transform);
+    insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);
 
     make_generator_state_argument_indirect(tcx, def_id, mir);
 
@@ -680,7 +684,7 @@ fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
 }
 
 fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
-    let return_block = insert_return_block(mir);
+    let return_block = insert_term_block(mir, TerminatorKind::Return);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(mir.basic_blocks().len());
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index e0f2a40ab07..7245b2daa12 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -26,6 +26,7 @@ use transform;
 
 pub mod add_validation;
 pub mod clean_end_regions;
+pub mod check_unsafety;
 pub mod simplify_branches;
 pub mod simplify;
 pub mod erase_regions;
@@ -46,6 +47,7 @@ pub mod nll;
 
 pub(crate) fn provide(providers: &mut Providers) {
     self::qualify_consts::provide(providers);
+    self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
         mir_const,
@@ -116,6 +118,7 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         // directly need the result or `mir_const_qualif`, so we can just force it.
         ty::queries::mir_const_qualif::force(tcx, DUMMY_SP, def_id);
     }
+    ty::queries::unsafety_violations::force(tcx, DUMMY_SP, def_id);
 
     let mut mir = tcx.mir_const(def_id).steal();
     transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
diff --git a/src/librustc_mir/transform/nll.rs b/src/librustc_mir/transform/nll/mod.rs
index bd02788df16..bd02788df16 100644
--- a/src/librustc_mir/transform/nll.rs
+++ b/src/librustc_mir/transform/nll/mod.rs
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index ca6eda5c2d7..339ea8a414b 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -380,10 +380,10 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         let mut promoter = Promoter {
             promoted: Mir::new(
                 IndexVec::new(),
-                Some(VisibilityScopeData {
-                    span,
-                    parent_scope: None
-                }).into_iter().collect(),
+                // FIXME: maybe try to filter this to avoid blowing up
+                // memory usage?
+                mir.visibility_scopes.clone(),
+                mir.visibility_scope_info.clone(),
                 IndexVec::new(),
                 ty,
                 None,
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index ffe444933a3..efb5b031809 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -122,14 +122,6 @@ impl<'a> AstValidator<'a> {
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
-    fn visit_lifetime(&mut self, lt: &'a Lifetime) {
-        if lt.ident.name == "'_" {
-            self.err_handler().span_err(lt.span, &format!("invalid lifetime name `{}`", lt.ident));
-        }
-
-        visit::walk_lifetime(self, lt)
-    }
-
     fn visit_expr(&mut self, expr: &'a Expr) {
         match expr.node {
             ExprKind::While(.., Some(ident)) |
diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml
index 439fa661e0a..c65312e9a83 100644
--- a/src/librustc_privacy/Cargo.toml
+++ b/src/librustc_privacy/Cargo.toml
@@ -10,5 +10,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 rustc = { path = "../librustc" }
+rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 0d5ad6f47c9..e7a1dd6b043 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -17,6 +17,7 @@
 
 #[macro_use] extern crate rustc;
 #[macro_use] extern crate syntax;
+extern crate rustc_typeck;
 extern crate syntax_pos;
 
 use rustc::hir::{self, PatKind};
@@ -658,65 +659,6 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
         }
         false
     }
-
-    fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self {
-        self.current_item = self.tcx.hir.local_def_id(item_id);
-        self.span = self.tcx.hir.span(item_id);
-        self
-    }
-
-    // Convenience methods for checking item interfaces
-    fn ty(&mut self) -> &mut Self {
-        self.tcx.type_of(self.current_item).visit_with(self);
-        self
-    }
-
-    fn generics(&mut self) -> &mut Self {
-        for def in &self.tcx.generics_of(self.current_item).types {
-            if def.has_default {
-                self.tcx.type_of(def.def_id).visit_with(self);
-            }
-        }
-        self
-    }
-
-    fn predicates(&mut self) -> &mut Self {
-        let predicates = self.tcx.predicates_of(self.current_item);
-        for predicate in &predicates.predicates {
-            predicate.visit_with(self);
-            match predicate {
-                &ty::Predicate::Trait(poly_predicate) => {
-                    self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
-                },
-                &ty::Predicate::Projection(poly_predicate) => {
-                    let tcx = self.tcx;
-                    self.check_trait_ref(
-                        poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
-                    );
-                },
-                _ => (),
-            };
-        }
-        self
-    }
-
-    fn impl_trait_ref(&mut self) -> &mut Self {
-        if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.current_item) {
-            self.check_trait_ref(impl_trait_ref);
-        }
-        self.tcx.predicates_of(self.current_item).visit_with(self);
-        self
-    }
-
-    fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
-        if !self.item_is_accessible(trait_ref.def_id) {
-            let msg = format!("trait `{}` is private", trait_ref);
-            self.tcx.sess.span_err(self.span, &msg);
-            return true;
-        }
-
-        trait_ref.super_visit_with(self)
-    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
@@ -733,6 +675,35 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         self.tables = orig_tables;
     }
 
+    fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty) {
+        self.span = hir_ty.span;
+        if let Some(ty) = self.tables.node_id_to_type_opt(hir_ty.hir_id) {
+            // Types in bodies.
+            if ty.visit_with(self) {
+                return;
+            }
+        } else {
+            // Types in signatures.
+            // FIXME: This is very ineffective. Ideally each HIR type should be converted
+            // into a semantic type only once and the result should be cached somehow.
+            if rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) {
+                return;
+            }
+        }
+
+        intravisit::walk_ty(self, hir_ty);
+    }
+
+    fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef) {
+        if !self.item_is_accessible(trait_ref.path.def.def_id()) {
+            let msg = format!("trait `{:?}` is private", trait_ref.path);
+            self.tcx.sess.span_err(self.span, &msg);
+            return;
+        }
+
+        intravisit::walk_trait_ref(self, trait_ref);
+    }
+
     // Check types of expressions
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         if self.check_expr_pat_type(expr.hir_id, expr.span) {
@@ -807,63 +778,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                                         item.id,
                                         &mut self.tables,
                                         self.empty_tables);
-
-        match item.node {
-            hir::ItemExternCrate(..) | hir::ItemMod(..) |
-            hir::ItemUse(..) | hir::ItemGlobalAsm(..) => {}
-            hir::ItemConst(..) | hir::ItemStatic(..) |
-            hir::ItemTy(..) | hir::ItemFn(..) => {
-                self.check_item(item.id).generics().predicates().ty();
-            }
-            hir::ItemTrait(.., ref trait_item_refs) => {
-                self.check_item(item.id).generics().predicates();
-                for trait_item_ref in trait_item_refs {
-                    let check = self.check_item(trait_item_ref.id.node_id);
-                    check.generics().predicates();
-                    if trait_item_ref.kind != hir::AssociatedItemKind::Type ||
-                       trait_item_ref.defaultness.has_value() {
-                        check.ty();
-                    }
-                }
-            }
-            hir::ItemEnum(ref def, _) => {
-                self.check_item(item.id).generics().predicates();
-                for variant in &def.variants {
-                    for field in variant.node.data.fields() {
-                        self.check_item(field.id).ty();
-                    }
-                }
-            }
-            hir::ItemForeignMod(ref foreign_mod) => {
-                for foreign_item in &foreign_mod.items {
-                    self.check_item(foreign_item.id).generics().predicates().ty();
-                }
-            }
-            hir::ItemStruct(ref struct_def, _) |
-            hir::ItemUnion(ref struct_def, _) => {
-                self.check_item(item.id).generics().predicates();
-                for field in struct_def.fields() {
-                    self.check_item(field.id).ty();
-                }
-            }
-            hir::ItemDefaultImpl(..) => {
-                self.check_item(item.id).impl_trait_ref();
-            }
-            hir::ItemImpl(.., ref trait_ref, _, ref impl_item_refs) => {
-                {
-                    let check = self.check_item(item.id);
-                    check.ty().generics().predicates();
-                    if trait_ref.is_some() {
-                        check.impl_trait_ref();
-                    }
-                }
-                for impl_item_ref in impl_item_refs {
-                    let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
-                    self.check_item(impl_item.id).generics().predicates().ty();
-                }
-            }
-        }
-
         self.current_item = self.tcx.hir.local_def_id(item.id);
         intravisit::walk_item(self, item);
         self.tables = orig_tables;
@@ -924,8 +838,13 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                 }
             }
             ty::TyProjection(ref proj) => {
-                let tcx = self.tcx;
-                if self.check_trait_ref(proj.trait_ref(tcx)) {
+                let trait_ref = proj.trait_ref(self.tcx);
+                if !self.item_is_accessible(trait_ref.def_id) {
+                    let msg = format!("trait `{}` is private", trait_ref);
+                    self.tcx.sess.span_err(self.span, &msg);
+                    return true;
+                }
+                if trait_ref.super_visit_with(self) {
                     return true;
                 }
             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 691329c608c..36cd69f91b9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -605,7 +605,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
                 ItemKind::Use(..) => {
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
-                    if item.span == DUMMY_SP {
+                    if item.span.ctxt().outer().expn_info().is_none() {
                         self.span = Some(item.span.with_hi(item.span.lo()));
                         self.found_use = true;
                         return;
@@ -615,11 +615,22 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
                 ItemKind::ExternCrate(_) => {}
                 // but place them before the first other item
                 _ => if self.span.map_or(true, |span| item.span < span ) {
-                    self.span = Some(item.span.with_hi(item.span.lo()));
+                    if item.span.ctxt().outer().expn_info().is_none() {
+                        // don't insert between attributes and an item
+                        if item.attrs.is_empty() {
+                            self.span = Some(item.span.with_hi(item.span.lo()));
+                        } else {
+                            // find the first attribute on the item
+                            for attr in &item.attrs {
+                                if self.span.map_or(true, |span| attr.span < span) {
+                                    self.span = Some(attr.span.with_hi(attr.span.lo()));
+                                }
+                            }
+                        }
+                    }
                 },
             }
         }
-        assert!(self.span.is_some(), "a file can't have no items and emit suggestions");
     }
 }
 
@@ -3553,8 +3564,7 @@ impl<'a> Resolver<'a> {
             };
             visit::walk_crate(&mut finder, krate);
             if !candidates.is_empty() {
-                let span = finder.span.expect("did not find module");
-                show_candidates(&mut err, span, &candidates, better, finder.found_use);
+                show_candidates(&mut err, finder.span, &candidates, better, finder.found_use);
             }
             err.emit();
         }
@@ -3748,7 +3758,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
 /// entities with that name in all crates. This method allows outputting the
 /// results of this search in a programmer-friendly way
 fn show_candidates(err: &mut DiagnosticBuilder,
-                   span: Span,
+                   // This is `None` if all placement locations are inside expansions
+                   span: Option<Span>,
                    candidates: &[ImportSuggestion],
                    better: bool,
                    found_use: bool) {
@@ -3766,18 +3777,27 @@ fn show_candidates(err: &mut DiagnosticBuilder,
     };
     let msg = format!("possible {}candidate{} into scope", better, msg_diff);
 
-    for candidate in &mut path_strings {
-        // produce an additional newline to separate the new use statement
-        // from the directly following item.
-        let additional_newline = if found_use {
-            ""
-        } else {
-            "\n"
-        };
-        *candidate = format!("use {};\n{}", candidate, additional_newline);
-    }
+    if let Some(span) = span {
+        for candidate in &mut path_strings {
+            // produce an additional newline to separate the new use statement
+            // from the directly following item.
+            let additional_newline = if found_use {
+                ""
+            } else {
+                "\n"
+            };
+            *candidate = format!("use {};\n{}", candidate, additional_newline);
+        }
 
-    err.span_suggestions(span, &msg, path_strings);
+        err.span_suggestions(span, &msg, path_strings);
+    } else {
+        let mut msg = msg;
+        msg.push(':');
+        for candidate in path_strings {
+            msg.push('\n');
+            msg.push_str(&candidate);
+        }
+    }
 }
 
 /// A somewhat inefficient routine to obtain the name of a module.
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 6f1f5b4a123..482350d04b5 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -32,4 +32,4 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 
 [target."cfg(windows)".dependencies]
-gcc = "0.3.50"
+cc = "1.0"
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 08266e86f97..619ea59ff1a 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate rustc_trans_utils;
-
 use super::archive::{ArchiveBuilder, ArchiveConfig};
 use super::linker::Linker;
 use super::command::Command;
@@ -20,17 +18,14 @@ use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, Pri
 use rustc::session::filesearch;
 use rustc::session::search_paths::PathKind;
 use rustc::session::Session;
-use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind};
+use rustc::middle::cstore::{NativeLibrary, LibSource, NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
 use {CrateTranslation, CrateInfo};
 use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
-use rustc::dep_graph::{DepKind, DepNode};
 use rustc::hir::def_id::CrateNum;
-use rustc::hir::svh::Svh;
 use rustc_back::tempdir::TempDir;
 use rustc_back::{PanicStrategy, RelroLevel};
-use rustc_incremental::IncrementalHashesMap;
 use context::get_reloc_model;
 use llvm;
 
@@ -89,17 +84,9 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize =
 pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize =
     RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;
 
-pub use self::rustc_trans_utils::link::{find_crate_name, filename_for_input,
-                                        default_output_for_target, invalid_output_for_target};
-
-pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta {
-    let krate_dep_node = &DepNode::new_no_params(DepKind::Krate);
-    let r = LinkMeta {
-        crate_hash: Svh::new(incremental_hashes_map[krate_dep_node].to_smaller_hash()),
-    };
-    info!("{:?}", r);
-    return r;
-}
+pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
+                                  invalid_output_for_target, build_link_meta, out_filename,
+                                  check_file_is_writeable};
 
 // The third parameter is for env vars, used on windows to set up the
 // path for MSVC to find its DLLs, and gcc to find its bundled
@@ -138,7 +125,7 @@ pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)>
 
 #[cfg(windows)]
 pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
-    use gcc::windows_registry;
+    use cc::windows_registry;
 
     let target = &sess.opts.target_triple;
     let tool = windows_registry::find_tool(target, "link.exe");
@@ -227,13 +214,6 @@ pub fn link_binary(sess: &Session,
     out_filenames
 }
 
-fn is_writeable(p: &Path) -> bool {
-    match p.metadata() {
-        Err(..) => true,
-        Ok(m) => !m.permissions().readonly()
-    }
-}
-
 fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
     let out_filename = outputs.single_output_file.clone()
         .unwrap_or(outputs
@@ -297,32 +277,6 @@ pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool {
     info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum)
 }
 
-fn out_filename(sess: &Session,
-                crate_type: config::CrateType,
-                outputs: &OutputFilenames,
-                crate_name: &str)
-                -> PathBuf {
-    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
-    let out_filename = outputs.outputs.get(&OutputType::Exe)
-                              .and_then(|s| s.to_owned())
-                              .or_else(|| outputs.single_output_file.clone())
-                              .unwrap_or(default_filename);
-
-    check_file_is_writeable(&out_filename, sess);
-
-    out_filename
-}
-
-// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
-// check this already -- however, the Linux linker will happily overwrite a
-// read-only file.  We should be consistent.
-fn check_file_is_writeable(file: &Path, sess: &Session) {
-    if !is_writeable(file) {
-        sess.fatal(&format!("output file {} is not writeable -- check its \
-                            permissions", file.display()));
-    }
-}
-
 fn link_binary_output(sess: &Session,
                       trans: &CrateTranslation,
                       crate_type: config::CrateType,
@@ -555,7 +509,7 @@ fn link_rlib<'a>(sess: &'a Session,
                 // of when we do and don't keep .#module-name#.bc files around.
                 let user_wants_numbered_bitcode =
                         sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
-                        sess.opts.cg.codegen_units > 1;
+                        sess.opts.codegen_units > 1;
                 if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
                     remove(sess, &bc_filename);
                 }
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index ef6bf2504f3..6b980a37ac7 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -939,10 +939,10 @@ fn produce_final_output_artifacts(sess: &Session,
         let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
 
         let keep_numbered_bitcode = needs_crate_bitcode ||
-                (user_wants_bitcode && sess.opts.cg.codegen_units > 1);
+                (user_wants_bitcode && sess.opts.codegen_units > 1);
 
         let keep_numbered_objects = needs_crate_object ||
-                (user_wants_objects && sess.opts.cg.codegen_units > 1);
+                (user_wants_objects && sess.opts.codegen_units > 1);
 
         for module in compiled_modules.modules.iter() {
             let module_name = Some(&module.name[..]);
@@ -1520,6 +1520,11 @@ fn start_executing_work(tcx: TyCtxt,
                                     total_llvm_time);
         }
 
+        // Regardless of what order these modules completed in, report them to
+        // the backend in the same order every time to ensure that we're handing
+        // out deterministic results.
+        compiled_modules.sort_by(|a, b| a.name.cmp(&b.name));
+
         let compiled_metadata_module = compiled_metadata_module
             .expect("Metadata module not compiled?");
 
@@ -1853,7 +1858,7 @@ impl OngoingCrateTranslation {
 
         // FIXME: time_llvm_passes support - does this use a global context or
         // something?
-        if sess.opts.cg.codegen_units == 1 && sess.time_llvm_passes() {
+        if sess.opts.codegen_units == 1 && sess.time_llvm_passes() {
             unsafe { llvm::LLVMRustPrintPassTimings(); }
         }
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index ba15f3522ac..774acc81343 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -41,12 +41,12 @@ use rustc::middle::trans::{Linkage, Visibility, Stats};
 use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
+use rustc::dep_graph::{DepNode, DepKind};
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
-use rustc::hir::map as hir_map;
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, NoDebugInfo};
 use rustc::session::Session;
-use rustc_incremental::{self, IncrementalHashesMap};
+use rustc_incremental;
 use abi;
 use allocator;
 use mir::lvalue::LvalueRef;
@@ -94,6 +94,8 @@ use syntax::ast;
 
 use mir::lvalue::Alignment;
 
+pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr};
+
 pub struct StatRecorder<'a, 'tcx: 'a> {
     ccx: &'a CrateContext<'a, 'tcx>,
     name: Option<String>,
@@ -659,20 +661,6 @@ pub fn set_link_section(ccx: &CrateContext,
     }
 }
 
-// check for the #[rustc_error] annotation, which forces an
-// error in trans. This is used to write compile-fail tests
-// that actually test that compilation succeeds without
-// reporting an error.
-fn check_for_rustc_errors_attr(tcx: TyCtxt) {
-    if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
-        let main_def_id = tcx.hir.local_def_id(id);
-
-        if tcx.has_attr(main_def_id, "rustc_error") {
-            tcx.sess.span_fatal(span, "compilation successful");
-        }
-    }
-}
-
 /// Create the `main` function which will initialize the rust runtime and call
 /// users main function.
 fn maybe_create_entry_wrapper(ccx: &CrateContext) {
@@ -884,63 +872,16 @@ fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter {
     }
 }
 
-/// The context provided lists a set of reachable ids as calculated by
-/// middle::reachable, but this contains far more ids and symbols than we're
-/// actually exposing from the object file. This function will filter the set in
-/// the context to the set of ids which correspond to symbols that are exposed
-/// from the object file being generated.
-///
-/// 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 {
-    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
-        // categories:
-        //
-        // 1. Those that are included statically via a static library
-        // 2. Those included otherwise (e.g. dynamically or via a framework)
-        //
-        // Although our LLVM module is not literally emitting code for the
-        // statically included symbols, it's an export of our library which
-        // needs to be passed on to the linker and encoded in the metadata.
-        //
-        // As a result, if this id is an FFI item (foreign item) then we only
-        // let it through if it's included statically.
-        match tcx.hir.get(id) {
-            hir_map::NodeForeignItem(..) => {
-                let def_id = tcx.hir.local_def_id(id);
-                tcx.is_statically_included_foreign_item(def_id)
-            }
-
-            // Only consider nodes that actually have exported symbols.
-            hir_map::NodeItem(&hir::Item {
-                node: hir::ItemStatic(..), .. }) |
-            hir_map::NodeItem(&hir::Item {
-                node: hir::ItemFn(..), .. }) |
-            hir_map::NodeImplItem(&hir::ImplItem {
-                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)
-            }
-
-            _ => false
-        }
-    }).collect()
-}
-
 pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             incremental_hashes_map: IncrementalHashesMap,
                              rx: mpsc::Receiver<Box<Any + Send>>)
                              -> OngoingCrateTranslation {
+
     check_for_rustc_errors_attr(tcx);
 
-    let link_meta = link::build_link_meta(&incremental_hashes_map);
+
+    let crate_hash = tcx.dep_graph
+                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
+    let link_meta = link::build_link_meta(crate_hash);
     let exported_symbol_node_ids = find_exported_symbols(tcx);
 
     let shared_ccx = SharedCrateContext::new(tcx);
@@ -980,7 +921,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ongoing_translation.translation_finished(tcx);
 
         assert_and_save_dep_graph(tcx,
-                                  incremental_hashes_map,
                                   metadata_incr_hashes,
                                   link_meta);
 
@@ -1113,7 +1053,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ongoing_translation.check_for_errors(tcx.sess);
 
     assert_and_save_dep_graph(tcx,
-                              incremental_hashes_map,
                               metadata_incr_hashes,
                               link_meta);
     ongoing_translation
@@ -1124,7 +1063,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 thread_local!(static DISPOSITIONS: RefCell<Vec<(String, Disposition)>> = Default::default());
 
 fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                       incremental_hashes_map: IncrementalHashesMap,
                                        metadata_incr_hashes: EncodedMetadataHashes,
                                        link_meta: LinkMeta) {
     time(tcx.sess.time_passes(),
@@ -1134,7 +1072,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     time(tcx.sess.time_passes(),
          "serialize dep graph",
          || rustc_incremental::save_dep_graph(tcx,
-                                              incremental_hashes_map,
                                               &metadata_incr_hashes,
                                               link_meta.crate_hash));
 }
@@ -1225,7 +1162,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
     let strategy = if tcx.sess.opts.debugging_opts.incremental.is_some() {
         PartitioningStrategy::PerModule
     } else {
-        PartitioningStrategy::FixedUnitCount(tcx.sess.opts.cg.codegen_units)
+        PartitioningStrategy::FixedUnitCount(tcx.sess.opts.codegen_units)
     };
 
     let codegen_units = time(time_passes, "codegen unit partitioning", || {
@@ -1238,7 +1175,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
             .collect::<Vec<_>>()
     });
 
-    assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() ||
+    assert!(tcx.sess.opts.codegen_units == codegen_units.len() ||
             tcx.sess.opts.debugging_opts.incremental.is_some());
 
     let translation_items: DefIdSet = items.iter().filter_map(|trans_item| {
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 57e9f1d091b..796dfd4417c 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -50,6 +50,7 @@ extern crate rustc_incremental;
 extern crate rustc_llvm as llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_const_math;
+extern crate rustc_trans_utils;
 extern crate rustc_demangle;
 extern crate jobserver;
 extern crate num_cpus;
@@ -60,7 +61,7 @@ extern crate syntax_pos;
 extern crate rustc_errors as errors;
 extern crate serialize;
 #[cfg(windows)]
-extern crate gcc; // Used to locate MSVC, not gcc :)
+extern crate cc; // Used to locate MSVC
 
 pub use base::trans_crate;
 
@@ -137,6 +138,63 @@ mod type_;
 mod type_of;
 mod value;
 
+use std::sync::mpsc;
+use std::any::Any;
+use rustc::ty::{self, TyCtxt};
+use rustc::session::Session;
+use rustc::session::config::OutputFilenames;
+use rustc::middle::cstore::MetadataLoader;
+use rustc::dep_graph::DepGraph;
+
+pub struct LlvmTransCrate(());
+
+impl LlvmTransCrate {
+    pub fn new() -> Self {
+        LlvmTransCrate(())
+    }
+}
+
+impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate {
+    type MetadataLoader = metadata::LlvmMetadataLoader;
+    type OngoingCrateTranslation = back::write::OngoingCrateTranslation;
+    type TranslatedCrate = CrateTranslation;
+
+    fn metadata_loader() -> Box<MetadataLoader> {
+        box metadata::LlvmMetadataLoader
+    }
+
+    fn provide_local(providers: &mut ty::maps::Providers) {
+        provide_local(providers);
+    }
+
+    fn provide_extern(providers: &mut ty::maps::Providers) {
+        provide_extern(providers);
+    }
+
+    fn trans_crate<'a, 'tcx>(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Self::OngoingCrateTranslation {
+        base::trans_crate(tcx, rx)
+    }
+
+    fn join_trans(
+        trans: Self::OngoingCrateTranslation,
+        sess: &Session,
+        dep_graph: &DepGraph
+    ) -> Self::TranslatedCrate {
+        trans.join(sess, dep_graph)
+    }
+
+    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
+        back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str());
+    }
+
+    fn dump_incremental_data(trans: &Self::TranslatedCrate) {
+        back::write::dump_incremental_data(trans);
+    }
+}
+
 pub struct ModuleTranslation {
     /// The name of the module. When the crate may be saved between
     /// compilations, incremental compilation requires that name be
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 2be7a81b1cd..62ccd55b483 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -112,7 +112,8 @@ fn resolve_associated_item<'a, 'tcx>(
            def_id, trait_id, rcvr_substs);
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
-    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, ty::Binder(trait_ref));
+    let vtbl = tcx.trans_fulfill_obligation(
+        DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), ty::Binder(trait_ref));
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
@@ -226,7 +227,8 @@ pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         substs: tcx.mk_substs_trait(source_ty, &[target_ty])
     });
 
-    match tcx.trans_fulfill_obligation(DUMMY_SP, trait_ref) {
+    match tcx.trans_fulfill_obligation(
+        DUMMY_SP, ty::ParamEnv::empty(traits::Reveal::All), trait_ref) {
         traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
             tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
         }
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 9b617c35d93..7c29186f465 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -108,11 +108,12 @@ use rustc::dep_graph::{DepNode, WorkProductId};
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::middle::trans::{Linkage, Visibility};
+use rustc::ich::Fingerprint;
 use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
 use rustc::ty::{self, TyCtxt, InstanceDef};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
-use rustc_incremental::IchHasher;
+use rustc_data_structures::stable_hasher::StableHasher;
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
 use syntax::ast::NodeId;
@@ -155,7 +156,7 @@ pub trait CodegenUnitExt<'tcx> {
     }
 
     fn compute_symbol_name_hash<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> u64 {
-        let mut state = IchHasher::new();
+        let mut state: StableHasher<Fingerprint> = StableHasher::new();
         let all_items = self.items_in_deterministic_order(tcx);
         for (item, (linkage, visibility)) in all_items {
             let symbol_name = item.symbol_name(tcx);
diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml
index f026d4fcbc2..bedbea00688 100644
--- a/src/librustc_trans_utils/Cargo.toml
+++ b/src/librustc_trans_utils/Cargo.toml
@@ -10,6 +10,12 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-rustc = { path = "../librustc" }
+ar = "0.3.0"
+flate2 = "0.2"
+owning_ref = "0.3.3"
+log = "0.3"
+
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc = { path = "../librustc" }
+rustc_back = { path = "../librustc_back" }
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 5e8abe59ad9..6873befd2bf 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -29,8 +29,89 @@
 
 #![cfg_attr(stage0, feature(const_fn))]
 
+extern crate ar;
+extern crate flate2;
+extern crate owning_ref;
+#[macro_use]
+extern crate log;
+
+#[macro_use]
 extern crate rustc;
+extern crate rustc_back;
 extern crate syntax;
 extern crate syntax_pos;
 
+use rustc::ty::TyCtxt;
+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 link;
+pub mod trans_crate;
+
+/// check for the #[rustc_error] annotation, which forces an
+/// error in trans. This is used to write compile-fail tests
+/// that actually test that compilation succeeds without
+/// reporting an error.
+pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
+    if let Some((id, span)) = *tcx.sess.entry_fn.borrow() {
+        let main_def_id = tcx.hir.local_def_id(id);
+
+        if tcx.has_attr(main_def_id, "rustc_error") {
+            tcx.sess.span_fatal(span, "compilation successful");
+        }
+    }
+}
+
+/// The context provided lists a set of reachable ids as calculated by
+/// middle::reachable, but this contains far more ids and symbols than we're
+/// actually exposing from the object file. This function will filter the set in
+/// the context to the set of ids which correspond to symbols that are exposed
+/// from the object file being generated.
+///
+/// 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 {
+    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
+        // categories:
+        //
+        // 1. Those that are included statically via a static library
+        // 2. Those included otherwise (e.g. dynamically or via a framework)
+        //
+        // Although our LLVM module is not literally emitting code for the
+        // statically included symbols, it's an export of our library which
+        // needs to be passed on to the linker and encoded in the metadata.
+        //
+        // As a result, if this id is an FFI item (foreign item) then we only
+        // let it through if it's included statically.
+        match tcx.hir.get(id) {
+            hir_map::NodeForeignItem(..) => {
+                let def_id = tcx.hir.local_def_id(id);
+                tcx.is_statically_included_foreign_item(def_id)
+            }
+
+            // Only consider nodes that actually have exported symbols.
+            hir_map::NodeItem(&hir::Item {
+                node: hir::ItemStatic(..), .. }) |
+            hir_map::NodeItem(&hir::Item {
+                node: hir::ItemFn(..), .. }) |
+            hir_map::NodeImplItem(&hir::ImplItem {
+                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)
+            }
+
+            _ => false
+        }
+    }).collect()
+}
diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs
index aa8637fabe8..47484488fb8 100644
--- a/src/librustc_trans_utils/link.rs
+++ b/src/librustc_trans_utils/link.rs
@@ -8,13 +8,56 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::ich::Fingerprint;
 use rustc::session::config::{self, OutputFilenames, Input, OutputType};
 use rustc::session::Session;
-use rustc::middle::cstore;
-use std::path::PathBuf;
+use rustc::middle::cstore::{self, LinkMeta};
+use rustc::hir::svh::Svh;
+use std::path::{Path, PathBuf};
 use syntax::ast;
 use syntax_pos::Span;
 
+pub fn out_filename(sess: &Session,
+                crate_type: config::CrateType,
+                outputs: &OutputFilenames,
+                crate_name: &str)
+                -> PathBuf {
+    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
+    let out_filename = outputs.outputs.get(&OutputType::Exe)
+                              .and_then(|s| s.to_owned())
+                              .or_else(|| outputs.single_output_file.clone())
+                              .unwrap_or(default_filename);
+
+    check_file_is_writeable(&out_filename, sess);
+
+    out_filename
+}
+
+// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
+// check this already -- however, the Linux linker will happily overwrite a
+// read-only file.  We should be consistent.
+pub fn check_file_is_writeable(file: &Path, sess: &Session) {
+    if !is_writeable(file) {
+        sess.fatal(&format!("output file {} is not writeable -- check its \
+                            permissions", file.display()));
+    }
+}
+
+fn is_writeable(p: &Path) -> bool {
+    match p.metadata() {
+        Err(..) => true,
+        Ok(m) => !m.permissions().readonly()
+    }
+}
+
+pub fn build_link_meta(crate_hash: Fingerprint) -> LinkMeta {
+    let r = LinkMeta {
+        crate_hash: Svh::new(crate_hash.to_smaller_hash()),
+    };
+    info!("{:?}", r);
+    return r;
+}
+
 pub fn find_crate_name(sess: Option<&Session>,
                        attrs: &[ast::Attribute],
                        input: &Input) -> String {
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
new file mode 100644
index 00000000000..f51a463fcc2
--- /dev/null
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -0,0 +1,249 @@
+// Copyright 2014-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.
+
+//! The Rust compiler.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+      html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![deny(warnings)]
+
+#![feature(box_syntax)]
+
+use std::any::Any;
+use std::io::prelude::*;
+use std::io::{self, Cursor};
+use std::fs::File;
+use std::path::Path;
+use std::sync::mpsc;
+
+use owning_ref::{ErasedBoxRef, OwningRef};
+use ar::{Archive, Builder, Header};
+use flate2::Compression;
+use flate2::write::DeflateEncoder;
+
+use syntax::symbol::Symbol;
+use rustc::hir::def_id::LOCAL_CRATE;
+use rustc::session::Session;
+use rustc::session::config::{CrateType, OutputFilenames};
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc::middle::cstore::EncodedMetadata;
+use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
+use rustc::dep_graph::{DepGraph, DepNode, DepKind};
+use rustc_back::target::Target;
+use link::{build_link_meta, out_filename};
+
+pub trait TransCrate {
+    type MetadataLoader: MetadataLoaderTrait;
+    type OngoingCrateTranslation;
+    type TranslatedCrate;
+
+    fn metadata_loader() -> Box<MetadataLoaderTrait>;
+    fn provide_local(_providers: &mut Providers);
+    fn provide_extern(_providers: &mut Providers);
+    fn trans_crate<'a, 'tcx>(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Self::OngoingCrateTranslation;
+    fn join_trans(
+        trans: Self::OngoingCrateTranslation,
+        sess: &Session,
+        dep_graph: &DepGraph
+    ) -> Self::TranslatedCrate;
+    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
+    fn dump_incremental_data(trans: &Self::TranslatedCrate);
+}
+
+pub struct DummyTransCrate;
+
+impl TransCrate for DummyTransCrate {
+    type MetadataLoader = DummyMetadataLoader;
+    type OngoingCrateTranslation = ();
+    type TranslatedCrate = ();
+
+    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+        box DummyMetadataLoader(())
+    }
+
+    fn provide_local(_providers: &mut Providers) {
+        bug!("DummyTransCrate::provide_local");
+    }
+
+    fn provide_extern(_providers: &mut Providers) {
+        bug!("DummyTransCrate::provide_extern");
+    }
+
+    fn trans_crate<'a, 'tcx>(
+        _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        _rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Self::OngoingCrateTranslation {
+        bug!("DummyTransCrate::trans_crate");
+    }
+
+    fn join_trans(
+        _trans: Self::OngoingCrateTranslation,
+        _sess: &Session,
+        _dep_graph: &DepGraph
+    ) -> Self::TranslatedCrate {
+        bug!("DummyTransCrate::join_trans");
+    }
+
+    fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
+        bug!("DummyTransCrate::link_binary");
+    }
+
+    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
+        bug!("DummyTransCrate::dump_incremental_data");
+    }
+}
+
+pub struct DummyMetadataLoader(());
+
+impl MetadataLoaderTrait for DummyMetadataLoader {
+    fn get_rlib_metadata(
+        &self,
+        _target: &Target,
+        _filename: &Path
+    ) -> Result<ErasedBoxRef<[u8]>, String> {
+        bug!("DummyMetadataLoader::get_rlib_metadata");
+    }
+
+    fn get_dylib_metadata(
+        &self,
+        _target: &Target,
+        _filename: &Path
+    ) -> Result<ErasedBoxRef<[u8]>, String> {
+        bug!("DummyMetadataLoader::get_dylib_metadata");
+    }
+}
+
+pub struct NoLlvmMetadataLoader;
+
+impl MetadataLoaderTrait for NoLlvmMetadataLoader {
+    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
+        let file = File::open(filename)
+            .map_err(|e| format!("metadata file open err: {:?}", e))?;
+        let mut archive = Archive::new(file);
+
+        while let Some(entry_result) = archive.next_entry() {
+            let mut entry = entry_result
+                .map_err(|e| format!("metadata section read err: {:?}", e))?;
+            if entry.header().identifier() == "rust.metadata.bin" {
+                let mut buf = Vec::new();
+                io::copy(&mut entry, &mut buf).unwrap();
+                let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
+                return Ok(buf.map_owner_box().erase_owner());
+            }
+        }
+
+        Err("Couldnt find metadata section".to_string())
+    }
+
+    fn get_dylib_metadata(
+        &self,
+        _target: &Target,
+        _filename: &Path,
+    ) -> Result<ErasedBoxRef<[u8]>, String> {
+        // FIXME: Support reading dylibs from llvm enabled rustc
+        self.get_rlib_metadata(_target, _filename)
+    }
+}
+
+pub struct MetadataOnlyTransCrate;
+pub struct OngoingCrateTranslation {
+    metadata: EncodedMetadata,
+    metadata_version: Vec<u8>,
+    crate_name: Symbol,
+}
+pub struct TranslatedCrate(OngoingCrateTranslation);
+
+impl MetadataOnlyTransCrate {
+    #[allow(dead_code)]
+    pub fn new() -> Self {
+        MetadataOnlyTransCrate
+    }
+}
+
+impl TransCrate for MetadataOnlyTransCrate {
+    type MetadataLoader = NoLlvmMetadataLoader;
+    type OngoingCrateTranslation = OngoingCrateTranslation;
+    type TranslatedCrate = TranslatedCrate;
+
+    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+        box NoLlvmMetadataLoader
+    }
+
+    fn provide_local(_providers: &mut Providers) {}
+    fn provide_extern(_providers: &mut Providers) {}
+
+    fn trans_crate<'a, 'tcx>(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        _rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Self::OngoingCrateTranslation {
+        ::check_for_rustc_errors_attr(tcx);
+        let _ = tcx.link_args(LOCAL_CRATE);
+        let _ = tcx.native_libraries(LOCAL_CRATE);
+        tcx.sess.abort_if_errors();
+
+        let crate_hash = tcx.dep_graph
+                        .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
+        let link_meta = build_link_meta(crate_hash);
+        let exported_symbols = ::find_exported_symbols(tcx);
+        let (metadata, _hashes) = tcx.encode_metadata(&link_meta, &exported_symbols);
+
+        OngoingCrateTranslation {
+            metadata: metadata,
+            metadata_version: tcx.metadata_encoding_version().to_vec(),
+            crate_name: tcx.crate_name(LOCAL_CRATE),
+        }
+    }
+
+    fn join_trans(
+        trans: Self::OngoingCrateTranslation,
+        _sess: &Session,
+        _dep_graph: &DepGraph,
+    ) -> Self::TranslatedCrate {
+        TranslatedCrate(trans)
+    }
+
+    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
+        for &crate_type in sess.opts.crate_types.iter() {
+            if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
+                continue;
+            }
+            let output_name =
+                out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
+            let mut compressed = trans.0.metadata_version.clone();
+            let metadata = if crate_type == CrateType::CrateTypeDylib {
+                DeflateEncoder::new(&mut compressed, Compression::Fast)
+                    .write_all(&trans.0.metadata.raw_data)
+                    .unwrap();
+                &compressed
+            } else {
+                &trans.0.metadata.raw_data
+            };
+            let mut builder = Builder::new(File::create(&output_name).unwrap());
+            let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
+            builder.append(&header, Cursor::new(metadata)).unwrap();
+        }
+
+        if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
+            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
+            sess.fatal("Executables are not supported by the metadata-only backend.");
+        }
+    }
+
+    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
+}
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5256bb22781..54fd070e93c 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -76,6 +76,8 @@ pub trait AstConv<'gcx, 'tcx> {
     /// used to help suppress derived errors typeck might otherwise
     /// report.
     fn set_tainted_by_errors(&self);
+
+    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
 }
 
 struct ConvertedBinding<'tcx> {
@@ -155,11 +157,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
     {
+
         let (substs, assoc_bindings) =
-            self.create_substs_for_ast_path(span,
-                                            def_id,
-                                            &item_segment.parameters,
-                                            None);
+            item_segment.with_parameters(|parameters| {
+                self.create_substs_for_ast_path(
+                    span,
+                    def_id,
+                    parameters,
+                    item_segment.infer_types,
+                    None)
+            });
 
         assoc_bindings.first().map(|b| self.prohibit_projection(b.span));
 
@@ -175,6 +182,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         span: Span,
         def_id: DefId,
         parameters: &hir::PathParameters,
+        infer_types: bool,
         self_ty: Option<Ty<'tcx>>)
         -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
     {
@@ -202,7 +210,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         // Check the number of type parameters supplied by the user.
         let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
-        if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
+        if !infer_types || num_types_provided > ty_param_defs.len() {
             check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
         }
 
@@ -238,7 +246,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             if i < num_types_provided {
                 // A provided type parameter.
                 self.ast_ty_to_ty(&parameters.types[i])
-            } else if parameters.infer_types {
+            } else if infer_types {
                 // No type parameters were provided, we can infer all.
                 let ty_var = if !default_needs_object_self(def) {
                     self.ty_infer_for_def(def, substs, span)
@@ -388,7 +396,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         let trait_def = self.tcx().trait_def(trait_def_id);
 
         if !self.tcx().sess.features.borrow().unboxed_closures &&
-           trait_segment.parameters.parenthesized != trait_def.paren_sugar {
+           trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar {
             // For now, require that parenthetical notation be used only with `Fn()` etc.
             let msg = if trait_def.paren_sugar {
                 "the precise format of `Fn`-family traits' type parameters is subject to change. \
@@ -400,10 +408,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                              span, GateIssue::Language, msg);
         }
 
-        self.create_substs_for_ast_path(span,
-                                        trait_def_id,
-                                        &trait_segment.parameters,
-                                        Some(self_ty))
+        trait_segment.with_parameters(|parameters| {
+            self.create_substs_for_ast_path(span,
+                                            trait_def_id,
+                                            parameters,
+                                            trait_segment.infer_types,
+                                            Some(self_ty))
+        })
     }
 
     fn trait_defines_associated_type_named(&self,
@@ -874,25 +885,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
     pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
         for segment in segments {
-            for typ in &segment.parameters.types {
-                struct_span_err!(self.tcx().sess, typ.span, E0109,
-                                 "type parameters are not allowed on this type")
-                    .span_label(typ.span, "type parameter not allowed")
-                    .emit();
-                break;
-            }
-            for lifetime in &segment.parameters.lifetimes {
-                struct_span_err!(self.tcx().sess, lifetime.span, E0110,
-                                 "lifetime parameters are not allowed on this type")
-                    .span_label(lifetime.span,
-                                "lifetime parameter not allowed on this type")
-                    .emit();
-                break;
-            }
-            for binding in &segment.parameters.bindings {
-                self.prohibit_projection(binding.span);
-                break;
-            }
+            segment.with_parameters(|parameters| {
+                for typ in &parameters.types {
+                    struct_span_err!(self.tcx().sess, typ.span, E0109,
+                                     "type parameters are not allowed on this type")
+                        .span_label(typ.span, "type parameter not allowed")
+                        .emit();
+                    break;
+                }
+                for lifetime in &parameters.lifetimes {
+                    struct_span_err!(self.tcx().sess, lifetime.span, E0110,
+                                     "lifetime parameters are not allowed on this type")
+                        .span_label(lifetime.span,
+                                    "lifetime parameter not allowed on this type")
+                        .emit();
+                    break;
+                }
+                for binding in &parameters.bindings {
+                    self.prohibit_projection(binding.span);
+                    break;
+                }
+            })
         }
     }
 
@@ -975,6 +988,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 }
             }
             Def::Err => {
+                for segment in &path.segments {
+                    segment.with_parameters(|parameters| {
+                        for ty in &parameters.types {
+                            self.ast_ty_to_ty(ty);
+                        }
+                        for binding in &parameters.bindings {
+                            self.ast_ty_to_ty(&binding.ty);
+                        }
+                    });
+                }
                 self.set_tainted_by_errors();
                 return self.tcx().types.err;
             }
@@ -1115,6 +1138,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
         };
 
+        self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
         result_ty
     }
 
@@ -1124,8 +1148,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                      -> Ty<'tcx>
     {
         match ty.node {
-            hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
-            hir::TyInfer => self.ty_infer(ty.span),
+            hir::TyInfer if expected_ty.is_some() => {
+                self.record_ty(ty.hir_id, expected_ty.unwrap(), ty.span);
+                expected_ty.unwrap()
+            }
             _ => self.ast_ty_to_ty(ty),
         }
     }
@@ -1214,19 +1240,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         let expected_ret_ty = expected_sig.as_ref().map(|e| e.output());
 
-        let is_infer = match decl.output {
-            hir::Return(ref output) if output.node == hir::TyInfer => true,
-            hir::DefaultReturn(..) => true,
-            _ => false
-        };
-
         let output_ty = match decl.output {
-            _ if is_infer && expected_ret_ty.is_some() =>
-                expected_ret_ty.unwrap(),
-            _ if is_infer => self.ty_infer(decl.output.span()),
-            hir::Return(ref output) =>
-                self.ast_ty_to_ty(&output),
-            hir::DefaultReturn(..) => bug!(),
+            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);
@@ -1298,15 +1327,16 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 if Some(trait_did) == tcx.lang_items().send_trait() ||
                     Some(trait_did) == tcx.lang_items().sync_trait() {
                     let segments = &bound.trait_ref.path.segments;
-                    let parameters = &segments[segments.len() - 1].parameters;
-                    if !parameters.types.is_empty() {
-                        check_type_argument_count(tcx, bound.trait_ref.path.span,
-                                                  parameters.types.len(), &[]);
-                    }
-                    if !parameters.lifetimes.is_empty() {
-                        report_lifetime_number_error(tcx, bound.trait_ref.path.span,
-                                                     parameters.lifetimes.len(), 0);
-                    }
+                    segments[segments.len() - 1].with_parameters(|parameters| {
+                        if !parameters.types.is_empty() {
+                            check_type_argument_count(tcx, bound.trait_ref.path.span,
+                                                      parameters.types.len(), &[]);
+                        }
+                        if !parameters.lifetimes.is_empty() {
+                            report_lifetime_number_error(tcx, bound.trait_ref.path.span,
+                                                         parameters.lifetimes.len(), 0);
+                        }
+                    });
                     true
                 } else {
                     false
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index cbf58209d05..d942b2d1230 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -787,11 +787,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             for field in variant.fields
                 .iter()
                 .filter(|field| !used_fields.contains_key(&field.name)) {
-                struct_span_err!(tcx.sess, span, E0027,
-                                "pattern does not mention field `{}`",
-                                field.name)
-                                .span_label(span, format!("missing field `{}`", field.name))
-                                .emit();
+                let mut diag = struct_span_err!(tcx.sess, span, E0027,
+                                                "pattern does not mention field `{}`",
+                                                field.name);
+                diag.span_label(span, format!("missing field `{}`", field.name));
+                if variant.ctor_kind == CtorKind::Fn {
+                    diag.note("trying to match a tuple variant with a struct variant pattern");
+                }
+                diag.emit();
             }
         }
     }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index cfcdbcc1195..94422f93e59 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -187,7 +187,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         }
 
         // Consider coercing the subtype to a DST
-        let unsize = self.coerce_unsized(a, b);
+        //
+        // NOTE: this is wrapped in a `commit_if_ok` because it creates
+        // a "spurious" type variable, and we don't want to have that
+        // type variable in memory if the coercion fails.
+        let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
         if unsize.is_ok() {
             debug!("coerce: unsize successful");
             return unsize;
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 65900dc3f36..7110a1ba81d 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -261,6 +261,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
                 None
             }
+            (_, &ty::TyRef(_, checked)) => {
+                // We have `&T`, check if what was expected was `T`. If so,
+                // we may want to suggest adding a `*`, or removing
+                // a `&`.
+                //
+                // (But, also check check the `expn_info()` to see if this is
+                // a macro; if so, it's hard to extract the text and make a good
+                // suggestion, so don't bother.)
+                if self.infcx.can_sub(self.param_env, checked.ty, &expected).is_ok() &&
+                   expr.span.ctxt().outer().expn_info().is_none() {
+                    match expr.node {
+                        // Maybe remove `&`?
+                        hir::ExprAddrOf(_, ref expr) => {
+                            if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+                                return Some(format!("try with `{}`", code));
+                            }
+                        }
+
+                        // Maybe add `*`? Only if `T: Copy`.
+                        _ => {
+                            if !self.infcx.type_moves_by_default(self.param_env,
+                                                                checked.ty,
+                                                                expr.span) {
+                                let sp = self.sess().codemap().call_span_if_macro(expr.span);
+                                if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) {
+                                    return Some(format!("try with `*{}`", code));
+                                }
+                            }
+                        },
+                    }
+                }
+                None
+            }
             _ => None,
         }
     }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 852134bbee3..a9830dd5dde 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -300,7 +300,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             if i < parent_substs.len() {
                 parent_substs.region_at(i)
             } else if let Some(lifetime)
-                    = provided.lifetimes.get(i - parent_substs.len()) {
+                    = provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
                 AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
             } else {
                 self.region_var_for_def(self.span, def)
@@ -310,7 +310,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             if i < parent_substs.len() {
                 parent_substs.type_at(i)
             } else if let Some(ast_ty)
-                    = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) {
+                = provided.as_ref().and_then(|p| {
+                    p.types.get(i - parent_substs.len() - method_generics.regions.len())
+                })
+            {
                 self.to_ty(ast_ty)
             } else {
                 self.type_var_for_def(self.span, def, cur_substs)
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 0afc482cb79..4ee0b4cb46f 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -70,6 +70,7 @@ pub struct NoMatchData<'tcx> {
     pub static_candidates: Vec<CandidateSource>,
     pub unsatisfied_predicates: Vec<TraitRef<'tcx>>,
     pub out_of_scope_traits: Vec<DefId>,
+    pub lev_candidate: Option<ty::AssociatedItem>,
     pub mode: probe::Mode,
 }
 
@@ -77,12 +78,14 @@ impl<'tcx> NoMatchData<'tcx> {
     pub fn new(static_candidates: Vec<CandidateSource>,
                unsatisfied_predicates: Vec<TraitRef<'tcx>>,
                out_of_scope_traits: Vec<DefId>,
+               lev_candidate: Option<ty::AssociatedItem>,
                mode: probe::Mode)
                -> Self {
         NoMatchData {
             static_candidates,
             unsatisfied_predicates,
             out_of_scope_traits,
+            lev_candidate,
             mode,
         }
     }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 7b947818325..a3b196f99d6 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -23,11 +23,13 @@ use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::util::nodemap::FxHashSet;
 use rustc::infer::{self, InferOk};
 use syntax::ast;
+use syntax::util::lev_distance::{lev_distance, find_best_match_for_name};
 use syntax_pos::Span;
 use rustc::hir;
 use std::mem;
 use std::ops::Deref;
 use std::rc::Rc;
+use std::cmp::max;
 
 use self::CandidateKind::*;
 pub use self::PickKind::*;
@@ -51,6 +53,10 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     /// used for error reporting
     static_candidates: Vec<CandidateSource>,
 
+    /// When probing for names, include names that are close to the
+    /// requested name (by Levensthein distance)
+    allow_similar_names: bool,
+
     /// Some(candidate) if there is a private candidate
     private_candidate: Option<Def>,
 
@@ -242,6 +248,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     return Err(MethodError::NoMatch(NoMatchData::new(Vec::new(),
                                                                      Vec::new(),
                                                                      Vec::new(),
+                                                                     None,
                                                                      mode)))
                 }
             }
@@ -261,7 +268,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // that we create during the probe process are removed later
         self.probe(|_| {
             let mut probe_cx =
-                ProbeContext::new(self, span, mode, method_name, return_type, steps);
+                ProbeContext::new(self, span, mode, method_name, return_type, Rc::new(steps));
 
             probe_cx.assemble_inherent_candidates();
             match scope {
@@ -333,7 +340,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
            mode: Mode,
            method_name: Option<ast::Name>,
            return_type: Option<Ty<'tcx>>,
-           steps: Vec<CandidateStep<'tcx>>)
+           steps: Rc<Vec<CandidateStep<'tcx>>>)
            -> ProbeContext<'a, 'gcx, 'tcx> {
         ProbeContext {
             fcx,
@@ -344,8 +351,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
             impl_dups: FxHashSet(),
-            steps: Rc::new(steps),
+            steps: steps,
             static_candidates: Vec::new(),
+            allow_similar_names: false,
             private_candidate: None,
             unsatisfied_predicates: Vec::new(),
         }
@@ -798,10 +806,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         if let Some(def) = private_candidate {
             return Err(MethodError::PrivateMatch(def, out_of_scope_traits));
         }
+        let lev_candidate = self.probe_for_lev_candidate()?;
 
         Err(MethodError::NoMatch(NoMatchData::new(static_candidates,
                                                   unsatisfied_predicates,
                                                   out_of_scope_traits,
+                                                  lev_candidate,
                                                   self.mode)))
     }
 
@@ -913,11 +923,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         debug!("applicable_candidates: {:?}", applicable_candidates);
 
         if applicable_candidates.len() > 1 {
-            match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
-                Some(pick) => {
-                    return Some(Ok(pick));
-                }
-                None => {}
+            if let Some(pick) = self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
+                return Some(Ok(pick));
             }
         }
 
@@ -1126,6 +1133,54 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         })
     }
 
+    /// Similarly to `probe_for_return_type`, this method attempts to find the best matching
+    /// candidate method where the method name may have been misspelt. Similarly to other
+    /// Levenshtein based suggestions, we provide at most one such suggestion.
+    fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssociatedItem>, MethodError<'tcx>> {
+        debug!("Probing for method names similar to {:?}",
+               self.method_name);
+
+        let steps = self.steps.clone();
+        self.probe(|_| {
+            let mut pcx = ProbeContext::new(self.fcx, self.span, self.mode, self.method_name,
+                                            self.return_type, steps);
+            pcx.allow_similar_names = true;
+            pcx.assemble_inherent_candidates();
+            pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID)?;
+
+            let method_names = pcx.candidate_method_names();
+            pcx.allow_similar_names = false;
+            let applicable_close_candidates: Vec<ty::AssociatedItem> = method_names
+                .iter()
+                .filter_map(|&method_name| {
+                    pcx.reset();
+                    pcx.method_name = Some(method_name);
+                    pcx.assemble_inherent_candidates();
+                    pcx.assemble_extension_candidates_for_traits_in_scope(ast::DUMMY_NODE_ID)
+                        .ok().map_or(None, |_| {
+                            pcx.pick_core()
+                                .and_then(|pick| pick.ok())
+                                .and_then(|pick| Some(pick.item))
+                        })
+                })
+               .collect();
+
+            if applicable_close_candidates.is_empty() {
+                Ok(None)
+            } else {
+                let best_name = {
+                    let names = applicable_close_candidates.iter().map(|cand| &cand.name);
+                    find_best_match_for_name(names,
+                                             &self.method_name.unwrap().as_str(),
+                                             None)
+                }.unwrap();
+                Ok(applicable_close_candidates
+                   .into_iter()
+                   .find(|method| method.name == best_name))
+            }
+        })
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // MISCELLANY
     fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool {
@@ -1253,10 +1308,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         self.tcx.erase_late_bound_regions(value)
     }
 
-    /// Find the method with the appropriate name (or return type, as the case may be).
+    /// Find the method with the appropriate name (or return type, as the case may be). If
+    /// `allow_similar_names` is set, find methods with close-matching names.
     fn impl_or_trait_item(&self, def_id: DefId) -> Vec<ty::AssociatedItem> {
         if let Some(name) = self.method_name {
-            self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x])
+            if self.allow_similar_names {
+                let max_dist = max(name.as_str().len(), 3) / 3;
+                self.tcx.associated_items(def_id)
+                    .filter(|x| {
+                        let dist = lev_distance(&*name.as_str(), &x.name.as_str());
+                        dist > 0 && dist <= max_dist
+                    })
+                    .collect()
+            } else {
+                self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x])
+            }
         } else {
             self.tcx.associated_items(def_id).collect()
         }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 7fa3dd7472d..90c5297b399 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -164,6 +164,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             MethodError::NoMatch(NoMatchData { static_candidates: static_sources,
                                                unsatisfied_predicates,
                                                out_of_scope_traits,
+                                               lev_candidate,
                                                mode,
                                                .. }) => {
                 let tcx = self.tcx;
@@ -282,6 +283,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                               item_name,
                                               rcvr_expr,
                                               out_of_scope_traits);
+
+                if let Some(lev_candidate) = lev_candidate {
+                    err.help(&format!("did you mean `{}`?", lev_candidate.name));
+                }
                 err.emit();
             }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index ae2430990ba..a0099a48c89 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1665,6 +1665,10 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     fn set_tainted_by_errors(&self) {
         self.infcx.set_tainted_by_errors()
     }
+
+    fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, _span: Span) {
+        self.write_ty(hir_id, ty)
+    }
 }
 
 /// Controls whether the arguments are tupled. This is used for the call
@@ -2232,7 +2236,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                adjusted_ty,
                index_ty);
 
-
         // First, try built-in indexing.
         match (adjusted_ty.builtin_index(), &index_ty.sty) {
             (Some(ty), &ty::TyUint(ast::UintTy::Us)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
@@ -4644,6 +4647,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // a problem.
         self.check_path_parameter_count(span, &mut type_segment, false);
         self.check_path_parameter_count(span, &mut fn_segment, false);
+        self.check_impl_trait(span, &mut fn_segment);
 
         let (fn_start, has_self) = match (type_segment, fn_segment) {
             (_, Some((_, generics))) => {
@@ -4664,7 +4668,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 i -= fn_start;
                 fn_segment
             };
-            let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
+            let lifetimes = segment.map_or(&[][..], |(s, _)| {
+                s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
+            });
 
             if let Some(lifetime) = lifetimes.get(i) {
                 AstConv::ast_region_to_region(self, lifetime, Some(def))
@@ -4688,7 +4694,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 fn_segment
             };
             let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
-                (&s.parameters.types[..], s.parameters.infer_types)
+                (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
             });
 
             // Skip over the lifetimes in the same segment.
@@ -4765,8 +4771,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   is_method_call: bool) {
         let (lifetimes, types, infer_types, bindings) = segment.map_or(
             (&[][..], &[][..], true, &[][..]),
-            |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
-                      s.parameters.infer_types, &s.parameters.bindings[..]));
+            |(s, _)| s.parameters.as_ref().map_or(
+                (&[][..], &[][..], s.infer_types, &[][..]),
+                |p| (&p.lifetimes[..], &p.types[..],
+                     s.infer_types, &p.bindings[..])));
         let infer_lifetimes = lifetimes.len() == 0;
 
         let count_lifetime_params = |n| {
@@ -4864,6 +4872,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    /// Report error if there is an explicit type parameter when using `impl Trait`.
+    fn check_impl_trait(&self,
+                        span: Span,
+                        segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) {
+        use hir::SyntheticTyParamKind::*;
+
+        segment.map(|(path_segment, generics)| {
+            let explicit = !path_segment.infer_types;
+            let impl_trait = generics.types.iter()
+                                           .any(|ty_param| {
+                                               match ty_param.synthetic {
+                                                   Some(ImplTrait) => true,
+                                                   _ => false,
+                                               }
+                                           });
+
+            if explicit && impl_trait {
+                let mut err = struct_span_err! {
+                    self.tcx.sess,
+                    span,
+                    E0632,
+                    "cannot provide explicit type parameters when `impl Trait` is \
+                    used in argument position."
+                };
+
+                err.emit();
+            }
+        });
+    }
+
     fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
                                             -> Ty<'tcx>
         where F: Fn() -> Ty<'tcx>
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index f17df8b22f3..ddbdd204305 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -523,7 +523,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
 
             let (span, name) = if index < ast_generics.lifetimes.len() {
                 (ast_generics.lifetimes[index].lifetime.span,
-                 ast_generics.lifetimes[index].lifetime.name)
+                 ast_generics.lifetimes[index].lifetime.name.name())
             } else {
                 let index = index - ast_generics.lifetimes.len();
                 (ast_generics.ty_params[index].span,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 7810d9049e1..3c650718a4b 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -207,6 +207,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
         let var_ty = self.resolve(&var_ty, &l.span);
         self.write_ty_to_tables(l.hir_id, var_ty);
     }
+
+    fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) {
+        intravisit::walk_ty(self, hir_ty);
+        let ty = self.fcx.node_ty(hir_ty.hir_id);
+        let ty = self.resolve(&ty, &hir_ty.span);
+        self.write_ty_to_tables(hir_ty.hir_id, ty);
+    }
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 79cb9147c18..25a37a2c48c 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -221,6 +221,10 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
     fn set_tainted_by_errors(&self) {
         // no obvious place to track this, just let it go
     }
+
+    fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
+        // no place to record types from signatures?
+    }
 }
 
 fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -918,6 +922,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         has_default: false,
                         object_lifetime_default: rl::Set1::Empty,
                         pure_wrt_drop: false,
+                        synthetic: None,
                     });
 
                     allow_defaults = true;
@@ -953,7 +958,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
     let regions = early_lifetimes.enumerate().map(|(i, l)| {
         ty::RegionParameterDef {
-            name: l.lifetime.name,
+            name: l.lifetime.name.name(),
             index: own_start + i as u32,
             def_id: tcx.hir.local_def_id(l.lifetime.id),
             pure_wrt_drop: l.pure_wrt_drop,
@@ -989,6 +994,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             object_lifetime_default:
                 object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
             pure_wrt_drop: p.pure_wrt_drop,
+            synthetic: p.synthetic,
         }
     });
     let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
@@ -1005,6 +1011,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
                 pure_wrt_drop: false,
+                synthetic: None,
             }));
         });
     }
@@ -1325,6 +1332,12 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
 fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            def_id: DefId)
                            -> ty::GenericPredicates<'tcx> {
+    explicit_predicates_of(tcx, def_id)
+}
+
+fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           def_id: DefId)
+                           -> ty::GenericPredicates<'tcx> {
     use rustc::hir::map::*;
     use rustc::hir::*;
 
@@ -1423,7 +1436,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir.local_def_id(param.lifetime.id),
             index,
-            name: param.lifetime.name
+            name: param.lifetime.name.name(),
         }));
         index += 1;
 
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 6bbe2233ff1..8df97355574 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4677,4 +4677,6 @@ register_diagnostics! {
     E0592, // duplicate definitions with name `{}`
 //  E0613, // Removed (merged with E0609)
     E0627, // yield statement outside of generator literal
+    E0632, // cannot provide explicit type parameters when `impl Trait` is used in
+           // argument position.
 }
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index 14e48b93029..15708ab766a 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -132,7 +132,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             !input_parameters.contains(&param)
         {
             report_unused_parameter(tcx, lifetime.lifetime.span,
-                                    "lifetime", &lifetime.lifetime.name.to_string());
+                                    "lifetime", &lifetime.lifetime.name.name().to_string());
         }
     }
 
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 61ac541e2c1..b295b414a03 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -18,4 +18,4 @@ html-diff = "0.0.4"
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.50"
+cc = "1.0"
diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs
index 830492dec94..97c9ca1e2d2 100644
--- a/src/librustdoc/build.rs
+++ b/src/librustdoc/build.rs
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 extern crate build_helper;
-extern crate gcc;
+extern crate cc;
 
 fn main() {
     let src_dir = std::path::Path::new("../rt/hoedown/src");
     build_helper::rerun_if_changed_anything_in_dir(src_dir);
-    let mut cfg = gcc::Build::new();
+    let mut cfg = cc::Build::new();
     cfg.file("../rt/hoedown/src/autolink.c")
        .file("../rt/hoedown/src/buffer.c")
        .file("../rt/hoedown/src/document.c")
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 095eb7797d4..c9afa3646b2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -876,7 +876,7 @@ impl Clean<Lifetime> for hir::Lifetime {
             }
             _ => {}
         }
-        Lifetime(self.name.to_string())
+        Lifetime(self.name.name().to_string())
     }
 }
 
@@ -884,14 +884,14 @@ impl Clean<Lifetime> for hir::LifetimeDef {
     fn clean(&self, _: &DocContext) -> Lifetime {
         if self.bounds.len() > 0 {
             let mut s = format!("{}: {}",
-                                self.lifetime.name.to_string(),
-                                self.bounds[0].name.to_string());
+                                self.lifetime.name.name(),
+                                self.bounds[0].name.name());
             for bound in self.bounds.iter().skip(1) {
-                s.push_str(&format!(" + {}", bound.name.to_string()));
+                s.push_str(&format!(" + {}", bound.name.name()));
             }
             Lifetime(s)
         } else {
-            Lifetime(self.lifetime.name.to_string())
+            Lifetime(self.lifetime.name.name().to_string())
         }
     }
 }
@@ -1852,25 +1852,27 @@ impl Clean<Type> for hir::Ty {
                 };
 
                 if let Some(&hir::ItemTy(ref ty, ref generics)) = alias {
-                    let provided_params = &path.segments.last().unwrap().parameters;
+                    let provided_params = &path.segments.last().unwrap();
                     let mut ty_substs = FxHashMap();
                     let mut lt_substs = FxHashMap();
-                    for (i, ty_param) in generics.ty_params.iter().enumerate() {
-                        let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
-                        if let Some(ty) = provided_params.types.get(i).cloned() {
-                            ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
-                        } else if let Some(default) = ty_param.default.clone() {
-                            ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
+                    provided_params.with_parameters(|provided_params| {
+                        for (i, ty_param) in generics.ty_params.iter().enumerate() {
+                            let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
+                            if let Some(ty) = provided_params.types.get(i).cloned() {
+                                ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
+                            } else if let Some(default) = ty_param.default.clone() {
+                                ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
+                            }
                         }
-                    }
-                    for (i, lt_param) in generics.lifetimes.iter().enumerate() {
-                        if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
-                            if !lt.is_elided() {
-                                let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
-                                lt_substs.insert(lt_def_id, lt.clean(cx));
+                        for (i, lt_param) in generics.lifetimes.iter().enumerate() {
+                            if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
+                                if !lt.is_elided() {
+                                    let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
+                                    lt_substs.insert(lt_def_id, lt.clean(cx));
+                                }
                             }
                         }
-                    }
+                    });
                     return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx));
                 }
                 resolve_type(cx, path.clean(cx), self.id)
@@ -2419,7 +2421,7 @@ impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext) -> PathSegment {
         PathSegment {
             name: self.name.clean(cx),
-            params: self.parameters.clean(cx)
+            params: self.with_parameters(|parameters| parameters.clean(cx))
         }
     }
 }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 1663e5ad142..2ecb7b546fc 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -175,7 +175,7 @@ pub fn run_core(search_paths: SearchPaths,
 
     let arena = DroplessArena::new();
     let arenas = GlobalArenas::new();
-    let hir_map = hir_map::map_crate(&mut hir_forest, &defs);
+    let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
     let output_filenames = driver::build_output_filenames(&input,
                                                           &None,
                                                           &None,
@@ -191,7 +191,7 @@ pub fn run_core(search_paths: SearchPaths,
                                                      &arenas,
                                                      &name,
                                                      &output_filenames,
-                                                     |tcx, analysis, _, _, result| {
+                                                     |tcx, analysis, _, result| {
         if let Err(_) = result {
             sess.fatal("Compilation failed, aborting rustdoc");
         }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 081f950e40d..98863b229b5 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -249,8 +249,8 @@ impl<'a> Classifier<'a> {
                 token::BinOpEq(..) | token::FatArrow => Class::Op,
 
             // Miscellaneous, no highlighting.
-            token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
-                token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
+            token::Dot | token::DotDot | token::DotDotDot | token::DotDotEq | token::Comma |
+                token::Semi | token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
                 token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
                 token::CloseDelim(token::NoDelim) => Class::None,
 
@@ -353,7 +353,7 @@ impl<'a> Classifier<'a> {
             token::Lifetime(..) => Class::Lifetime,
 
             token::Underscore | token::Eof | token::Interpolated(..) |
-            token::Tilde | token::At => Class::None,
+            token::Tilde | token::At | token::DotEq => Class::None,
         };
 
         // Anything that didn't return above is the simple case where we the
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index e1e52b9428a..485e75443fe 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2621,7 +2621,8 @@ fn render_assoc_item(w: &mut fmt::Formatter,
                 href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
             }
         };
-        let mut head_len = format!("{}{}{:#}fn {}{:#}",
+        let mut head_len = format!("{}{}{}{:#}fn {}{:#}",
+                                   VisSpace(&meth.visibility),
                                    ConstnessSpace(constness),
                                    UnsafetySpace(unsafety),
                                    AbiSpace(abi),
@@ -2633,8 +2634,9 @@ fn render_assoc_item(w: &mut fmt::Formatter,
         } else {
             (0, true)
         };
-        write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
+        write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
+               VisSpace(&meth.visibility),
                ConstnessSpace(constness),
                UnsafetySpace(unsafety),
                AbiSpace(abi),
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 5727d3c5f70..1b7232bf1bc 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -823,7 +823,7 @@ span.since {
 
 .information {
 	position: absolute;
-	left: -1px;
+	left: -20px;
 	margin-top: 7px;
 	z-index: 1;
 }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 36efc37a809..7fa1b38bdad 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -124,7 +124,7 @@ pub fn run(input: &str,
                                        render_type);
 
     {
-        let map = hir::map::map_crate(&mut hir_forest, &defs);
+        let map = hir::map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
         let krate = map.krate();
         let mut hir_collector = HirCollector {
             sess: &sess,
@@ -348,7 +348,21 @@ pub fn make_test(s: &str,
             }
         }
     }
-    if dont_insert_main || s.contains("fn main") {
+
+    // FIXME (#21299): prefer libsyntax or some other actual parser over this
+    // best-effort ad hoc approach
+    let already_has_main = s.lines()
+        .map(|line| {
+            let comment = line.find("//");
+            if let Some(comment_begins) = comment {
+                &line[0..comment_begins]
+            } else {
+                line
+            }
+        })
+        .any(|code| code.contains("fn main"));
+
+    if dont_insert_main || already_has_main {
         prog.push_str(&everything_else);
     } else {
         prog.push_str("fn main() {\n");
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 09c16816934..fb276448ffa 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -36,7 +36,7 @@ rustc_tsan = { path = "../librustc_tsan" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.50"
+cc = "1.0"
 
 [features]
 backtrace = []
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 19ea25fc7df..7ca762c801a 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -11,7 +11,7 @@
 #![deny(warnings)]
 
 extern crate build_helper;
-extern crate gcc;
+extern crate cc;
 
 use std::env;
 use std::process::Command;
@@ -68,8 +68,8 @@ fn main() {
         if cfg!(feature = "backtrace") {
             println!("cargo:rustc-link-lib=backtrace");
         }
-        println!("cargo:rustc-link-lib=magenta");
-        println!("cargo:rustc-link-lib=mxio");
+        println!("cargo:rustc-link-lib=zircon");
+        println!("cargo:rustc-link-lib=fdio");
         println!("cargo:rustc-link-lib=launchpad"); // for std::process
     }
 }
@@ -77,7 +77,7 @@ fn main() {
 fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
     let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
 
-    let compiler = gcc::Build::new().get_compiler();
+    let compiler = cc::Build::new().get_compiler();
     // only msvc returns None for ar so unwrap is okay
     let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
     let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 96af2272578..7d000d7c859 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -691,6 +691,17 @@ impl<K, V, S> HashMap<K, V, S>
     /// Returns a reference to the map's [`BuildHasher`].
     ///
     /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::RandomState;
+    ///
+    /// let hasher = RandomState::new();
+    /// let map: HashMap<isize, isize> = HashMap::with_hasher(hasher);
+    /// let hasher: &RandomState = map.hasher();
+    /// ```
     #[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
     pub fn hasher(&self) -> &S {
         &self.hash_builder
@@ -2191,6 +2202,36 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
     fn take_key(&mut self) -> Option<K> {
         self.key.take()
     }
+
+    /// Replaces the entry, returning the old key and value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_replace)]
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<String, u32> = HashMap::new();
+    /// map.insert("poneyland".to_string(), 15);
+    ///
+    /// if let Entry::Occupied(entry) = map.entry("poneyland".to_string()) {
+    ///     let (old_key, old_value): (String, u32) = entry.replace(16);
+    ///     assert_eq!(old_key, "poneyland");
+    ///     assert_eq!(old_value, 15);
+    /// }
+    ///
+    /// assert_eq!(map.get("poneyland"), Some(&16));
+    /// ```
+    #[unstable(feature = "map_entry_replace", issue = "44286")]
+    pub fn replace(mut self, value: V) -> (K, V) {
+        let (old_key, old_value) = self.elem.read_mut();
+
+        let old_key = mem::replace(old_key, self.key.unwrap());
+        let old_value = mem::replace(old_value, value);
+
+        (old_key, old_value)
+    }
 }
 
 impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 72d1946a286..231b0be9276 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -56,6 +56,7 @@ use any::TypeId;
 use borrow::Cow;
 use cell;
 use char;
+use convert;
 use core::array;
 use fmt::{self, Debug, Display};
 use mem::transmute;
@@ -370,6 +371,13 @@ impl Error for char::ParseCharError {
     }
 }
 
+#[unstable(feature = "try_from", issue = "33417")]
+impl Error for convert::Infallible {
+    fn description(&self) -> &str {
+        match *self {
+        }
+    }
+}
 
 // copied from any.rs
 impl Error + 'static {
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 2a916b819cc..91600b01298 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1595,9 +1595,9 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 ///
 /// Notable exception is made for situations where any of the directories
 /// specified in the `path` could not be created as it was being created concurrently.
-/// Such cases are considered success. In other words: calling `create_dir_all`
-/// concurrently from multiple threads or processes is guaranteed to not fail
-/// due to race itself.
+/// Such cases are considered to be successful. That is, calling `create_dir_all`
+/// concurrently from multiple threads or processes is guaranteed not to fail
+/// due to a race condition with itself.
 ///
 /// # Examples
 ///
@@ -2161,6 +2161,27 @@ mod tests {
     }
 
     #[test]
+    #[cfg(unix)]
+    fn set_get_unix_permissions() {
+        use os::unix::fs::PermissionsExt;
+
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("set_get_unix_permissions");
+        check!(fs::create_dir(filename));
+        let mask = 0o7777;
+
+        check!(fs::set_permissions(filename,
+                                   fs::Permissions::from_mode(0)));
+        let metadata0 = check!(fs::metadata(filename));
+        assert_eq!(mask & metadata0.permissions().mode(), 0);
+
+        check!(fs::set_permissions(filename,
+                                   fs::Permissions::from_mode(0o1777)));
+        let metadata1 = check!(fs::metadata(filename));
+        assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
+    }
+
+    #[test]
     #[cfg(windows)]
     fn file_test_io_seek_read_write() {
         use os::windows::fs::FileExt;
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index e20f249d3ea..45d281ee34a 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -40,9 +40,10 @@ use mem;
 ///
 /// io::copy(&mut reader, &mut writer)?;
 ///
-/// assert_eq!(reader, &writer[..]);
+/// assert_eq!(&b"hello"[..], &writer[..]);
 /// # Ok(())
 /// # }
+/// # foo().unwrap();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index aff9af66444..8d1e7882e5d 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -167,7 +167,7 @@ impl TcpStream {
     /// connection request.
     ///
     /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-    #[stable(feature = "tcpstream_connect_timeout", since = "1.22.0")]
+    #[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
         net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
     }
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 76ef36cc9a7..1edb35d8fe7 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -710,6 +710,10 @@ mod prim_u128 { }
 //
 /// The pointer-sized signed integer type.
 ///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+///
 /// *[See also the `std::isize` module](isize/index.html).*
 ///
 /// However, please note that examples are shared between primitive integer
@@ -722,6 +726,10 @@ mod prim_isize { }
 //
 /// The pointer-sized unsigned integer type.
 ///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+///
 /// *[See also the `std::usize` module](usize/index.html).*
 ///
 /// However, please note that examples are shared between primitive integer
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index a3a7e91dd80..1869ad3ed70 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -106,15 +106,18 @@ use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 pub struct Child {
     handle: imp::Process,
 
-    /// The handle for writing to the child's stdin, if it has been captured
+    /// The handle for writing to the child's standard input (stdin), if it has
+    /// been captured.
     #[stable(feature = "process", since = "1.0.0")]
     pub stdin: Option<ChildStdin>,
 
-    /// The handle for reading from the child's stdout, if it has been captured
+    /// The handle for reading from the child's standard output (stdout), if it
+    /// has been captured.
     #[stable(feature = "process", since = "1.0.0")]
     pub stdout: Option<ChildStdout>,
 
-    /// The handle for reading from the child's stderr, if it has been captured
+    /// The handle for reading from the child's standard error (stderr), if it
+    /// has been captured.
     #[stable(feature = "process", since = "1.0.0")]
     pub stderr: Option<ChildStderr>,
 }
@@ -149,12 +152,17 @@ impl fmt::Debug for Child {
     }
 }
 
-/// A handle to a child process's stdin.
+/// A handle to a child process's standard input (stdin).
 ///
 /// This struct is used in the [`stdin`] field on [`Child`].
 ///
+/// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying
+/// file handle will be closed. If the child process was blocked on input prior
+/// to being dropped, it will become unblocked after dropping.
+///
 /// [`Child`]: struct.Child.html
 /// [`stdin`]: struct.Child.html#structfield.stdin
+/// [dropped]: ../ops/trait.Drop.html
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdin {
     inner: AnonPipe
@@ -192,12 +200,16 @@ impl fmt::Debug for ChildStdin {
     }
 }
 
-/// A handle to a child process's stdout.
+/// A handle to a child process's standard output (stdout).
 ///
 /// This struct is used in the [`stdout`] field on [`Child`].
 ///
+/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
+/// underlying file handle will be closed.
+///
 /// [`Child`]: struct.Child.html
 /// [`stdout`]: struct.Child.html#structfield.stdout
+/// [dropped]: ../ops/trait.Drop.html
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdout {
     inner: AnonPipe
@@ -239,8 +251,12 @@ impl fmt::Debug for ChildStdout {
 ///
 /// This struct is used in the [`stderr`] field on [`Child`].
 ///
+/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
+/// underlying file handle will be closed.
+///
 /// [`Child`]: struct.Child.html
 /// [`stderr`]: struct.Child.html#structfield.stderr
+/// [dropped]: ../ops/trait.Drop.html
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStderr {
     inner: AnonPipe
@@ -534,7 +550,7 @@ impl Command {
         self
     }
 
-    /// Configuration for the child process's stdin handle (file descriptor 0).
+    /// Configuration for the child process's standard input (stdin) handle.
     ///
     /// # Examples
     ///
@@ -554,7 +570,7 @@ impl Command {
         self
     }
 
-    /// Configuration for the child process's stdout handle (file descriptor 1).
+    /// Configuration for the child process's standard output (stdout) handle.
     ///
     /// # Examples
     ///
@@ -574,7 +590,7 @@ impl Command {
         self
     }
 
-    /// Configuration for the child process's stderr handle (file descriptor 2).
+    /// Configuration for the child process's standard error (stderr) handle.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 5c5231f4e84..4757faabfb8 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -24,19 +24,24 @@ use sys_common::rwlock as sys;
 /// of the underlying data (exclusive access) and the read portion of this lock
 /// typically allows for read-only access (shared access).
 ///
+/// In comparison, a [`Mutex`] does not distinguish between readers or writers
+/// that aquire the lock, therefore blocking any threads waiting for the lock to
+/// become available. An `RwLock` will allow any number of readers to aquire the
+/// lock as long as a writer is not holding the lock.
+///
 /// The priority policy of the lock is dependent on the underlying operating
 /// system's implementation, and this type does not guarantee that any
 /// particular policy will be used.
 ///
 /// The type parameter `T` represents the data that this lock protects. It is
-/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
-/// allow concurrent access through readers. The RAII guards returned from the
-/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
-/// to allow access to the contained of the lock.
+/// required that `T` satisfies [`Send`] to be shared across threads and
+/// [`Sync`] to allow concurrent access through readers. The RAII guards
+/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
+/// for the `write` methods) to allow access to the contained of the lock.
 ///
 /// # Poisoning
 ///
-/// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however,
+/// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however,
 /// that an `RwLock` may only be poisoned if a panic occurs while it is locked
 /// exclusively (write mode). If a panic occurs in any reader, then the lock
 /// will not be poisoned.
@@ -63,6 +68,12 @@ use sys_common::rwlock as sys;
 ///     assert_eq!(*w, 6);
 /// } // write lock is dropped here
 /// ```
+///
+/// [`Deref`]: ../../std/ops/trait.Deref.html
+/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
+/// [`Send`]: ../../std/marker/trait.Send.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
+/// [`Mutex`]: struct.Mutex.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RwLock<T: ?Sized> {
     inner: Box<sys::RWLock>,
@@ -154,6 +165,24 @@ impl<T: ?Sized> RwLock<T> {
     /// # Panics
     ///
     /// This function might panic when called if the lock is already held by the current thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::{Arc, RwLock};
+    /// use std::thread;
+    ///
+    /// let lock = Arc::new(RwLock::new(1));
+    /// let c_lock = lock.clone();
+    ///
+    /// let n = lock.read().unwrap();
+    /// assert_eq!(*n, 1);
+    ///
+    /// thread::spawn(move || {
+    ///     let r = c_lock.read();
+    ///     assert!(r.is_ok());
+    /// }).join().unwrap();
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@@ -180,6 +209,19 @@ impl<T: ?Sized> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock. An
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::RwLock;
+    ///
+    /// let lock = RwLock::new(1);
+    ///
+    /// match lock.try_read() {
+    ///     Ok(n) => assert_eq!(*n, 1),
+    ///     Err(_) => unreachable!(),
+    /// };
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
@@ -210,6 +252,19 @@ impl<T: ?Sized> RwLock<T> {
     /// # Panics
     ///
     /// This function might panic when called if the lock is already held by the current thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::RwLock;
+    ///
+    /// let lock = RwLock::new(1);
+    ///
+    /// let mut n = lock.write().unwrap();
+    /// *n = 2;
+    ///
+    /// assert!(lock.try_read().is_err());
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
@@ -236,6 +291,19 @@ impl<T: ?Sized> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock. An
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::RwLock;
+    ///
+    /// let lock = RwLock::new(1);
+    ///
+    /// let n = lock.read().unwrap();
+    /// assert_eq!(*n, 1);
+    ///
+    /// assert!(lock.try_write().is_err());
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
@@ -253,6 +321,22 @@ impl<T: ?Sized> RwLock<T> {
     /// If another thread is active, the lock can still become poisoned at any
     /// time.  You should not trust a `false` value for program correctness
     /// without additional synchronization.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::{Arc, RwLock};
+    /// use std::thread;
+    ///
+    /// let lock = Arc::new(RwLock::new(0));
+    /// let c_lock = lock.clone();
+    ///
+    /// let _ = thread::spawn(move || {
+    ///     let _lock = c_lock.write().unwrap();
+    ///     panic!(); // the lock gets poisoned
+    /// }).join();
+    /// assert_eq!(lock.is_poisoned(), true);
+    /// ```
     #[inline]
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn is_poisoned(&self) -> bool {
@@ -267,6 +351,19 @@ impl<T: ?Sized> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock. An
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::RwLock;
+    ///
+    /// let lock = RwLock::new(String::new());
+    /// {
+    ///     let mut s = lock.write().unwrap();
+    ///     *s = "modified".to_owned();
+    /// }
+    /// assert_eq!(lock.into_inner().unwrap(), "modified");
+    /// ```
     #[stable(feature = "rwlock_into_inner", since = "1.6.0")]
     pub fn into_inner(self) -> LockResult<T> where T: Sized {
         // We know statically that there are no outstanding references to
@@ -282,7 +379,7 @@ impl<T: ?Sized> RwLock<T> {
                 (ptr::read(inner), ptr::read(poison), ptr::read(data))
             };
             mem::forget(self);
-            inner.destroy();  // Keep in sync with the `Drop` impl.
+            inner.destroy(); // Keep in sync with the `Drop` impl.
             drop(inner);
 
             poison::map_result(poison.borrow(), |_| data.into_inner())
@@ -300,6 +397,16 @@ impl<T: ?Sized> RwLock<T> {
     /// is poisoned whenever a writer panics while holding an exclusive lock. An
     /// error will only be returned if the lock would have otherwise been
     /// acquired.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::RwLock;
+    ///
+    /// let mut lock = RwLock::new(0);
+    /// *lock.get_mut().unwrap() = 10;
+    /// assert_eq!(*lock.read().unwrap(), 10);
+    /// ```
     #[stable(feature = "rwlock_get_mut", since = "1.6.0")]
     pub fn get_mut(&mut self) -> LockResult<&mut T> {
         // We know statically that there are no other references to `self`, so
@@ -486,7 +593,7 @@ mod tests {
     fn test_rw_arc_poison_wr() {
         let arc = Arc::new(RwLock::new(1));
         let arc2 = arc.clone();
-        let _: Result<(), _> = thread::spawn(move|| {
+        let _: Result<(), _> = thread::spawn(move || {
             let _lock = arc2.write().unwrap();
             panic!();
         }).join();
@@ -498,7 +605,7 @@ mod tests {
         let arc = Arc::new(RwLock::new(1));
         assert!(!arc.is_poisoned());
         let arc2 = arc.clone();
-        let _: Result<(), _> = thread::spawn(move|| {
+        let _: Result<(), _> = thread::spawn(move || {
             let _lock = arc2.write().unwrap();
             panic!();
         }).join();
@@ -510,7 +617,7 @@ mod tests {
     fn test_rw_arc_no_poison_rr() {
         let arc = Arc::new(RwLock::new(1));
         let arc2 = arc.clone();
-        let _: Result<(), _> = thread::spawn(move|| {
+        let _: Result<(), _> = thread::spawn(move || {
             let _lock = arc2.read().unwrap();
             panic!();
         }).join();
@@ -521,7 +628,7 @@ mod tests {
     fn test_rw_arc_no_poison_rw() {
         let arc = Arc::new(RwLock::new(1));
         let arc2 = arc.clone();
-        let _: Result<(), _> = thread::spawn(move|| {
+        let _: Result<(), _> = thread::spawn(move || {
             let _lock = arc2.read().unwrap();
             panic!()
         }).join();
@@ -535,7 +642,7 @@ mod tests {
         let arc2 = arc.clone();
         let (tx, rx) = channel();
 
-        thread::spawn(move|| {
+        thread::spawn(move || {
             let mut lock = arc2.write().unwrap();
             for _ in 0..10 {
                 let tmp = *lock;
@@ -550,7 +657,7 @@ mod tests {
         let mut children = Vec::new();
         for _ in 0..5 {
             let arc3 = arc.clone();
-            children.push(thread::spawn(move|| {
+            children.push(thread::spawn(move || {
                 let lock = arc3.read().unwrap();
                 assert!(*lock >= 0);
             }));
@@ -571,7 +678,7 @@ mod tests {
     fn test_rw_arc_access_in_unwind() {
         let arc = Arc::new(RwLock::new(1));
         let arc2 = arc.clone();
-        let _ = thread::spawn(move|| -> () {
+        let _ = thread::spawn(move || -> () {
             struct Unwinder {
                 i: Arc<RwLock<isize>>,
             }
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index f44b9aa9615..3e631ad40ac 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -68,8 +68,8 @@ impl FileExt for fs::File {
 /// Unix-specific extensions to `Permissions`
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
-    /// Returns the underlying raw `mode_t` bits that are the standard Unix
-    /// permissions for this file.
+    /// Returns the underlying raw `st_mode` bits that contain the standard
+    /// Unix permissions for this file.
     ///
     /// # Examples
     ///
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 13112fc1fa5..c4616c3b395 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -95,7 +95,7 @@ pub struct DirBuilder { mode: mode_t }
 impl FileAttr {
     pub fn size(&self) -> u64 { self.stat.st_size as u64 }
     pub fn perm(&self) -> FilePermissions {
-        FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
+        FilePermissions { mode: (self.stat.st_mode as mode_t) }
     }
 
     pub fn file_type(&self) -> FileType {
diff --git a/src/libstd/sys/unix/process/mod.rs b/src/libstd/sys/unix/process/mod.rs
index b50384d8eee..2a331069bc2 100644
--- a/src/libstd/sys/unix/process/mod.rs
+++ b/src/libstd/sys/unix/process/mod.rs
@@ -19,4 +19,4 @@ mod process_inner;
 #[path = "process_fuchsia.rs"]
 mod process_inner;
 #[cfg(target_os = "fuchsia")]
-mod magenta;
+mod zircon;
diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs
index 7d583cb3dfc..5d34da04446 100644
--- a/src/libstd/sys/unix/process/process_fuchsia.rs
+++ b/src/libstd/sys/unix/process/process_fuchsia.rs
@@ -13,7 +13,7 @@ use libc;
 use mem;
 use ptr;
 
-use sys::process::magenta::{Handle, mx_handle_t};
+use sys::process::zircon::{Handle, zx_handle_t};
 use sys::process::process_common::*;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -51,10 +51,10 @@ impl Command {
     }
 
     unsafe fn do_exec(&mut self, stdio: ChildPipes)
-                      -> io::Result<mx_handle_t> {
-        use sys::process::magenta::*;
+                      -> io::Result<zx_handle_t> {
+        use sys::process::zircon::*;
 
-        let job_handle = mx_job_default();
+        let job_handle = zx_job_default();
         let envp = match *self.get_envp() {
             Some(ref envp) => envp.as_ptr(),
             None => ptr::null(),
@@ -67,39 +67,39 @@ impl Command {
         }
 
         // Duplicate the job handle
-        let mut job_copy: mx_handle_t = MX_HANDLE_INVALID;
-        mx_cvt(mx_handle_duplicate(job_handle, MX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
+        let mut job_copy: zx_handle_t = ZX_HANDLE_INVALID;
+        zx_cvt(zx_handle_duplicate(job_handle, ZX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
         // Create a launchpad
         let mut launchpad: *mut launchpad_t = ptr::null_mut();
-        mx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
+        zx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
         let launchpad_destructor = LaunchpadDestructor(launchpad);
 
         // Set the process argv
-        mx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1,
+        zx_cvt(launchpad_set_args(launchpad, self.get_argv().len() as i32 - 1,
                                   self.get_argv().as_ptr()))?;
         // Setup the environment vars
-        mx_cvt(launchpad_set_environ(launchpad, envp))?;
-        mx_cvt(launchpad_add_vdso_vmo(launchpad))?;
+        zx_cvt(launchpad_set_environ(launchpad, envp))?;
+        zx_cvt(launchpad_add_vdso_vmo(launchpad))?;
         // Load the executable
-        mx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?;
-        mx_cvt(launchpad_load_vdso(launchpad, MX_HANDLE_INVALID))?;
-        mx_cvt(launchpad_clone(launchpad, LP_CLONE_MXIO_ROOT | LP_CLONE_MXIO_CWD))?;
+        zx_cvt(launchpad_elf_load(launchpad, launchpad_vmo_from_file(self.get_argv()[0])))?;
+        zx_cvt(launchpad_load_vdso(launchpad, ZX_HANDLE_INVALID))?;
+        zx_cvt(launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE | LP_CLONE_FDIO_CWD))?;
 
         // Clone stdin, stdout, and stderr
         if let Some(fd) = stdio.stdin.fd() {
-            mx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
+            zx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
         } else {
-            mx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
+            zx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
         }
         if let Some(fd) = stdio.stdout.fd() {
-            mx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
+            zx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
         } else {
-            mx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
+            zx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
         }
         if let Some(fd) = stdio.stderr.fd() {
-            mx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
+            zx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
         } else {
-            mx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
+            zx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
         }
 
         // We don't want FileDesc::drop to be called on any stdio. It would close their fds. The
@@ -113,9 +113,9 @@ impl Command {
         // `launchpad_go` destroys the launchpad, so we must not
         mem::forget(launchpad_destructor);
 
-        let mut process_handle: mx_handle_t = 0;
+        let mut process_handle: zx_handle_t = 0;
         let mut err_msg: *const libc::c_char = ptr::null();
-        mx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?;
+        zx_cvt(launchpad_go(launchpad, &mut process_handle, &mut err_msg))?;
         // FIXME: See if we want to do something with that err_msg
 
         Ok(process_handle)
@@ -136,27 +136,27 @@ impl Process {
     }
 
     pub fn kill(&mut self) -> io::Result<()> {
-        use sys::process::magenta::*;
+        use sys::process::zircon::*;
 
-        unsafe { mx_cvt(mx_task_kill(self.handle.raw()))?; }
+        unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; }
 
         Ok(())
     }
 
     pub fn wait(&mut self) -> io::Result<ExitStatus> {
         use default::Default;
-        use sys::process::magenta::*;
+        use sys::process::zircon::*;
 
-        let mut proc_info: mx_info_process_t = Default::default();
-        let mut actual: mx_size_t = 0;
-        let mut avail: mx_size_t = 0;
+        let mut proc_info: zx_info_process_t = Default::default();
+        let mut actual: zx_size_t = 0;
+        let mut avail: zx_size_t = 0;
 
         unsafe {
-            mx_cvt(mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
-                                      MX_TIME_INFINITE, ptr::null_mut()))?;
-            mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
+            zx_cvt(zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
+                                      ZX_TIME_INFINITE, ptr::null_mut()))?;
+            zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS,
                                       &mut proc_info as *mut _ as *mut libc::c_void,
-                                      mem::size_of::<mx_info_process_t>(), &mut actual,
+                                      mem::size_of::<zx_info_process_t>(), &mut actual,
                                       &mut avail))?;
         }
         if actual != 1 {
@@ -168,14 +168,14 @@ impl Process {
 
     pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
         use default::Default;
-        use sys::process::magenta::*;
+        use sys::process::zircon::*;
 
-        let mut proc_info: mx_info_process_t = Default::default();
-        let mut actual: mx_size_t = 0;
-        let mut avail: mx_size_t = 0;
+        let mut proc_info: zx_info_process_t = Default::default();
+        let mut actual: zx_size_t = 0;
+        let mut avail: zx_size_t = 0;
 
         unsafe {
-            let status = mx_object_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
+            let status = zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED,
                                             0, ptr::null_mut());
             match status {
                 0 => { }, // Success
@@ -184,9 +184,9 @@ impl Process {
                 },
                 _ => { panic!("Failed to wait on process handle: {}", status); },
             }
-            mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
+            zx_cvt(zx_object_get_info(self.handle.raw(), ZX_INFO_PROCESS,
                                       &mut proc_info as *mut _ as *mut libc::c_void,
-                                      mem::size_of::<mx_info_process_t>(), &mut actual,
+                                      mem::size_of::<zx_info_process_t>(), &mut actual,
                                       &mut avail))?;
         }
         if actual != 1 {
diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/zircon.rs
index bc20a74f114..b5ec11b40fd 100644
--- a/src/libstd/sys/unix/process/magenta.rs
+++ b/src/libstd/sys/unix/process/zircon.rs
@@ -17,31 +17,31 @@ use u64;
 
 use libc::{c_int, c_void};
 
-pub type mx_handle_t = i32;
-pub type mx_vaddr_t = usize;
-pub type mx_rights_t = u32;
-pub type mx_status_t = i32;
+pub type zx_handle_t = i32;
+pub type zx_vaddr_t = usize;
+pub type zx_rights_t = u32;
+pub type zx_status_t = i32;
 
-pub type mx_size_t = usize;
+pub type zx_size_t = usize;
 
-pub const MX_HANDLE_INVALID: mx_handle_t = 0;
+pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
 
-pub type mx_time_t = u64;
-pub const MX_TIME_INFINITE : mx_time_t = u64::MAX;
+pub type zx_time_t = u64;
+pub const ZX_TIME_INFINITE : zx_time_t = u64::MAX;
 
-pub type mx_signals_t = u32;
+pub type zx_signals_t = u32;
 
-pub const MX_OBJECT_SIGNAL_3         : mx_signals_t = 1 << 3;
+pub const ZX_OBJECT_SIGNAL_3         : zx_signals_t = 1 << 3;
 
-pub const MX_TASK_TERMINATED        : mx_signals_t = MX_OBJECT_SIGNAL_3;
+pub const ZX_TASK_TERMINATED        : zx_signals_t = ZX_OBJECT_SIGNAL_3;
 
-pub const MX_RIGHT_SAME_RIGHTS  : mx_rights_t = 1 << 31;
+pub const ZX_RIGHT_SAME_RIGHTS  : zx_rights_t = 1 << 31;
 
-pub type mx_object_info_topic_t = u32;
+pub type zx_object_info_topic_t = u32;
 
-pub const MX_INFO_PROCESS         : mx_object_info_topic_t = 3;
+pub const ZX_INFO_PROCESS         : zx_object_info_topic_t = 3;
 
-pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
+pub fn zx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<zx_status_t>+Copy {
     if let Ok(status) = TryInto::try_into(t) {
         if status < 0 {
             Err(io::Error::from_raw_os_error(status))
@@ -53,33 +53,33 @@ pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
     }
 }
 
-// Safe wrapper around mx_handle_t
+// Safe wrapper around zx_handle_t
 pub struct Handle {
-    raw: mx_handle_t,
+    raw: zx_handle_t,
 }
 
 impl Handle {
-    pub fn new(raw: mx_handle_t) -> Handle {
+    pub fn new(raw: zx_handle_t) -> Handle {
         Handle {
             raw,
         }
     }
 
-    pub fn raw(&self) -> mx_handle_t {
+    pub fn raw(&self) -> zx_handle_t {
         self.raw
     }
 }
 
 impl Drop for Handle {
     fn drop(&mut self) {
-        unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
+        unsafe { zx_cvt(zx_handle_close(self.raw)).expect("Failed to close zx_handle_t"); }
     }
 }
 
-// Common MX_INFO header
+// Common ZX_INFO header
 #[derive(Default)]
 #[repr(C)]
-pub struct mx_info_header_t {
+pub struct zx_info_header_t {
     pub topic: u32,              // identifies the info struct
     pub avail_topic_size: u16,   // “native” size of the struct
     pub topic_size: u16,         // size of the returned struct (<=topic_size)
@@ -89,34 +89,34 @@ pub struct mx_info_header_t {
 
 #[derive(Default)]
 #[repr(C)]
-pub struct mx_record_process_t {
+pub struct zx_record_process_t {
     pub return_code: c_int,
 }
 
-// Returned for topic MX_INFO_PROCESS
+// Returned for topic ZX_INFO_PROCESS
 #[derive(Default)]
 #[repr(C)]
-pub struct mx_info_process_t {
-    pub hdr: mx_info_header_t,
-    pub rec: mx_record_process_t,
+pub struct zx_info_process_t {
+    pub hdr: zx_info_header_t,
+    pub rec: zx_record_process_t,
 }
 
 extern {
-    pub fn mx_job_default() -> mx_handle_t;
+    pub fn zx_job_default() -> zx_handle_t;
 
-    pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;
+    pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;
 
-    pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;
+    pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;
 
-    pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,
-                               out: *const mx_handle_t) -> mx_handle_t;
+    pub fn zx_handle_duplicate(handle: zx_handle_t, rights: zx_rights_t,
+                               out: *const zx_handle_t) -> zx_handle_t;
 
-    pub fn mx_object_wait_one(handle: mx_handle_t, signals: mx_signals_t, timeout: mx_time_t,
-                              pending: *mut mx_signals_t) -> mx_status_t;
+    pub fn zx_object_wait_one(handle: zx_handle_t, signals: zx_signals_t, timeout: zx_time_t,
+                              pending: *mut zx_signals_t) -> zx_status_t;
 
-    pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
-                              buffer_size: mx_size_t, actual_size: *mut mx_size_t,
-                              avail: *mut mx_size_t) -> mx_status_t;
+    pub fn zx_object_get_info(handle: zx_handle_t, topic: u32, buffer: *mut c_void,
+                              buffer_size: zx_size_t, actual_size: *mut zx_size_t,
+                              avail: *mut zx_size_t) -> zx_status_t;
 }
 
 // From `enum special_handles` in system/ulib/launchpad/launchpad.c
@@ -133,117 +133,117 @@ pub struct launchpad_t {
     env: *const c_char,
     env_len: usize,
 
-    handles: *mut mx_handle_t,
+    handles: *mut zx_handle_t,
     handles_info: *mut u32,
     handle_count: usize,
     handle_alloc: usize,
 
-    entry: mx_vaddr_t,
-    base: mx_vaddr_t,
-    vdso_base: mx_vaddr_t,
+    entry: zx_vaddr_t,
+    base: zx_vaddr_t,
+    vdso_base: zx_vaddr_t,
 
     stack_size: usize,
 
-    special_handles: [mx_handle_t; HND_SPECIAL_COUNT],
+    special_handles: [zx_handle_t; HND_SPECIAL_COUNT],
     loader_message: bool,
 }
 
 extern {
-    pub fn launchpad_create(job: mx_handle_t, name: *const c_char,
-                            lp: *mut *mut launchpad_t) -> mx_status_t;
+    pub fn launchpad_create(job: zx_handle_t, name: *const c_char,
+                            lp: *mut *mut launchpad_t) -> zx_status_t;
 
     pub fn launchpad_go(lp: *mut launchpad_t,
-                        proc_handle: *mut mx_handle_t,
-                        err_msg: *mut *const c_char) -> mx_status_t;
+                        proc_handle: *mut zx_handle_t,
+                        err_msg: *mut *const c_char) -> zx_status_t;
 
     pub fn launchpad_destroy(lp: *mut launchpad_t);
 
     pub fn launchpad_set_args(lp: *mut launchpad_t, argc: c_int,
-                               argv: *const *const c_char) -> mx_status_t;
+                               argv: *const *const c_char) -> zx_status_t;
 
-    pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> mx_status_t;
+    pub fn launchpad_set_environ(lp: *mut launchpad_t, envp: *const *const c_char) -> zx_status_t;
 
-    pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> mx_status_t;
+    pub fn launchpad_clone(lp: *mut launchpad_t, what: u32) -> zx_status_t;
 
-    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
+    pub fn launchpad_clone_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
 
-    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> mx_status_t;
+    pub fn launchpad_transfer_fd(lp: *mut launchpad_t, fd: c_int, target_fd: c_int) -> zx_status_t;
 
-    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
+    pub fn launchpad_elf_load(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
 
-    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> mx_status_t;
+    pub fn launchpad_add_vdso_vmo(lp: *mut launchpad_t) -> zx_status_t;
 
-    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: mx_handle_t) -> mx_status_t;
+    pub fn launchpad_load_vdso(lp: *mut launchpad_t, vmo: zx_handle_t) -> zx_status_t;
 
-    pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
+    pub fn launchpad_vmo_from_file(filename: *const c_char) -> zx_handle_t;
 }
 
 // Launchpad clone constants
 
-pub const LP_CLONE_MXIO_ROOT: u32 = 0x0001;
-pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
-// LP_CLONE_MXIO_STDIO = 0x0004
-// LP_CLONE_MXIO_ALL = 0x00FF
+pub const LP_CLONE_FDIO_NAMESPACE: u32 = 0x0001;
+pub const LP_CLONE_FDIO_CWD: u32 = 0x0002;
+// LP_CLONE_FDIO_STDIO = 0x0004
+// LP_CLONE_FDIO_ALL = 0x00FF
 // LP_CLONE_ENVIRON = 0x0100
 // LP_CLONE_DEFAULT_JOB = 0x0200
 // LP_CLONE_ALL = 0xFFFF
 
 // Errors
 
-#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1;
+#[allow(unused)] pub const ERR_INTERNAL: zx_status_t = -1;
 
 // ERR_NOT_SUPPORTED: The operation is not implemented, supported,
 // or enabled.
-#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2;
+#[allow(unused)] pub const ERR_NOT_SUPPORTED: zx_status_t = -2;
 
 // ERR_NO_RESOURCES: The system was not able to allocate some resource
 // needed for the operation.
-#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3;
+#[allow(unused)] pub const ERR_NO_RESOURCES: zx_status_t = -3;
 
 // ERR_NO_MEMORY: The system was not able to allocate memory needed
 // for the operation.
-#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4;
+#[allow(unused)] pub const ERR_NO_MEMORY: zx_status_t = -4;
 
-// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete
+// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete
 // successfully.
-#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5;
+#[allow(unused)] pub const ERR_CALL_FAILED: zx_status_t = -5;
 
 // ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
 // retried.  This should not be seen outside of the VDSO.
-#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6;
+#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6;
 
 // ======= Parameter errors =======
 // ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
-#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10;
+#[allow(unused)] pub const ERR_INVALID_ARGS: zx_status_t = -10;
 
 // ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
-#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11;
+#[allow(unused)] pub const ERR_BAD_HANDLE: zx_status_t = -11;
 
 // ERR_WRONG_TYPE: The subject of the operation is the wrong type to
 // perform the operation.
 // Example: Attempting a message_read on a thread handle.
-#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12;
+#[allow(unused)] pub const ERR_WRONG_TYPE: zx_status_t = -12;
 
 // ERR_BAD_SYSCALL: The specified syscall number is invalid.
-#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13;
+#[allow(unused)] pub const ERR_BAD_SYSCALL: zx_status_t = -13;
 
 // ERR_OUT_OF_RANGE: An argument is outside the valid range for this
 // operation.
-#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14;
+#[allow(unused)] pub const ERR_OUT_OF_RANGE: zx_status_t = -14;
 
 // ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
 // this operation.
-#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15;
+#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15;
 
 // ======= Precondition or state errors =======
 // ERR_BAD_STATE: operation failed because the current state of the
 // object does not allow it, or a precondition of the operation is
 // not satisfied
-#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20;
+#[allow(unused)] pub const ERR_BAD_STATE: zx_status_t = -20;
 
 // ERR_TIMED_OUT: The time limit for the operation elapsed before
 // the operation completed.
-#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21;
+#[allow(unused)] pub const ERR_TIMED_OUT: zx_status_t = -21;
 
 // ERR_SHOULD_WAIT: The operation cannot be performed currently but
 // potentially could succeed if the caller waits for a prerequisite
@@ -253,67 +253,67 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002;
 // messages waiting but has an open remote will return ERR_SHOULD_WAIT.
 // Attempting to read from a message pipe that has no messages waiting
 // and has a closed remote end will return ERR_REMOTE_CLOSED.
-#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22;
+#[allow(unused)] pub const ERR_SHOULD_WAIT: zx_status_t = -22;
 
 // ERR_CANCELED: The in-progress operation (e.g. a wait) has been
 // // canceled.
-#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23;
+#[allow(unused)] pub const ERR_CANCELED: zx_status_t = -23;
 
 // ERR_PEER_CLOSED: The operation failed because the remote end
 // of the subject of the operation was closed.
-#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24;
+#[allow(unused)] pub const ERR_PEER_CLOSED: zx_status_t = -24;
 
 // ERR_NOT_FOUND: The requested entity is not found.
-#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25;
+#[allow(unused)] pub const ERR_NOT_FOUND: zx_status_t = -25;
 
 // ERR_ALREADY_EXISTS: An object with the specified identifier
 // already exists.
 // Example: Attempting to create a file when a file already exists
 // with that name.
-#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26;
+#[allow(unused)] pub const ERR_ALREADY_EXISTS: zx_status_t = -26;
 
 // ERR_ALREADY_BOUND: The operation failed because the named entity
 // is already owned or controlled by another entity. The operation
 // could succeed later if the current owner releases the entity.
-#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27;
+#[allow(unused)] pub const ERR_ALREADY_BOUND: zx_status_t = -27;
 
 // ERR_UNAVAILABLE: The subject of the operation is currently unable
 // to perform the operation.
 // Note: This is used when there's no direct way for the caller to
 // observe when the subject will be able to perform the operation
 // and should thus retry.
-#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28;
+#[allow(unused)] pub const ERR_UNAVAILABLE: zx_status_t = -28;
 
 // ======= Permission check errors =======
 // ERR_ACCESS_DENIED: The caller did not have permission to perform
 // the specified operation.
-#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30;
+#[allow(unused)] pub const ERR_ACCESS_DENIED: zx_status_t = -30;
 
 // ======= Input-output errors =======
 // ERR_IO: Otherwise unspecified error occurred during I/O.
-#[allow(unused)] pub const ERR_IO: mx_status_t = -40;
+#[allow(unused)] pub const ERR_IO: zx_status_t = -40;
 
 // ERR_REFUSED: The entity the I/O operation is being performed on
 // rejected the operation.
 // Example: an I2C device NAK'ing a transaction or a disk controller
 // rejecting an invalid command.
-#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41;
+#[allow(unused)] pub const ERR_IO_REFUSED: zx_status_t = -41;
 
 // ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
 // check and is possibly corrupted.
 // Example: CRC or Parity error.
-#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42;
+#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42;
 
 // ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
 // and may be permanently lost.
 // Example: A disk block is irrecoverably damaged.
-#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43;
+#[allow(unused)] pub const ERR_IO_DATA_LOSS: zx_status_t = -43;
 
 // Filesystem specific errors
-#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50;
-#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51;
-#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52;
+#[allow(unused)] pub const ERR_BAD_PATH: zx_status_t = -50;
+#[allow(unused)] pub const ERR_NOT_DIR: zx_status_t = -51;
+#[allow(unused)] pub const ERR_NOT_FILE: zx_status_t = -52;
 // ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
-#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53;
+#[allow(unused)] pub const ERR_FILE_BIG: zx_status_t = -53;
 // ERR_NO_SPACE: Filesystem or device space is exhausted.
-#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54;
+#[allow(unused)] pub const ERR_NO_SPACE: zx_status_t = -54;
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 1f56a299407..fd066c9cdbe 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -344,15 +344,15 @@ mod imp {
     use io;
     use rand::Rng;
 
-    #[link(name = "magenta")]
+    #[link(name = "zircon")]
     extern {
-        fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
+        fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
     }
 
     fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
         unsafe {
             let mut actual = 0;
-            let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
+            let status = zx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
             if status == 0 {
                 Ok(actual)
             } else {
@@ -387,7 +387,7 @@ mod imp {
                 let ret = getrandom(buf);
                 match ret {
                     Err(err) => {
-                        panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
+                        panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
                             err, buf.len())
                     }
                     Ok(actual) => {
diff --git a/src/libstd/sys_common/poison.rs b/src/libstd/sys_common/poison.rs
index 3c61593acc5..934ac3edbf1 100644
--- a/src/libstd/sys_common/poison.rs
+++ b/src/libstd/sys_common/poison.rs
@@ -65,6 +65,31 @@ pub struct Guard {
 /// each lock, but once a lock is poisoned then all future acquisitions will
 /// return this error.
 ///
+/// # Examples
+///
+/// ```
+/// use std::sync::{Arc, Mutex};
+/// use std::thread;
+///
+/// let mutex = Arc::new(Mutex::new(1));
+///
+/// // poison the mutex
+/// let c_mutex = mutex.clone();
+/// let _ = thread::spawn(move || {
+///     let mut data = c_mutex.lock().unwrap();
+///     *data = 2;
+///     panic!();
+/// }).join();
+///
+/// match mutex.lock() {
+///     Ok(_) => unreachable!(),
+///     Err(p_err) => {
+///         let data = p_err.get_ref();
+///         println!("recovered: {}", data);
+///     }
+/// };
+/// ```
+///
 /// [`Mutex`]: ../../std/sync/struct.Mutex.html
 /// [`RwLock`]: ../../std/sync/struct.RwLock.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -72,10 +97,16 @@ pub struct PoisonError<T> {
     guard: T,
 }
 
-/// An enumeration of possible errors which can occur while calling the
-/// [`try_lock`] method.
+/// An enumeration of possible errors associated with a [`TryLockResult`] which
+/// can occur while trying to aquire a lock, from the [`try_lock`] method on a
+/// [`Mutex`] or the [`try_read`] and [`try_write`] methods on an [`RwLock`].
 ///
+/// [`Mutex`]: struct.Mutex.html
+/// [`RwLock`]: struct.RwLock.html
+/// [`TryLockResult`]: type.TryLockResult.html
 /// [`try_lock`]: struct.Mutex.html#method.try_lock
+/// [`try_read`]: struct.RwLock.html#method.try_read
+/// [`try_write`]: struct.RwLock.html#method.try_write
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum TryLockError<T> {
     /// The lock could not be acquired because another thread failed while holding
@@ -148,6 +179,28 @@ impl<T> PoisonError<T> {
 
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashSet;
+    /// use std::sync::{Arc, Mutex};
+    /// use std::thread;
+    ///
+    /// let mutex = Arc::new(Mutex::new(HashSet::new()));
+    ///
+    /// // poison the mutex
+    /// let c_mutex = mutex.clone();
+    /// let _ = thread::spawn(move || {
+    ///     let mut data = c_mutex.lock().unwrap();
+    ///     data.insert(10);
+    ///     panic!();
+    /// }).join();
+    ///
+    /// let p_err = mutex.lock().unwrap_err();
+    /// let data = p_err.into_inner();
+    /// println!("recovered {} items", data.len());
+    /// ```
     #[stable(feature = "sync_poison", since = "1.2.0")]
     pub fn into_inner(self) -> T { self.guard }
 
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index d715a0d740b..86927ce322e 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -13,7 +13,9 @@ use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
 
 const NANOS_PER_SEC: u32 = 1_000_000_000;
 const NANOS_PER_MILLI: u32 = 1_000_000;
+const NANOS_PER_MICRO: u32 = 1_000;
 const MILLIS_PER_SEC: u64 = 1_000;
+const MICROS_PER_SEC: u64 = 1_000_000;
 
 /// A `Duration` type to represent a span of time, typically used for system
 /// timeouts.
@@ -116,6 +118,27 @@ impl Duration {
         Duration { secs: secs, nanos: nanos }
     }
 
+    /// Creates a new `Duration` from the specified number of microseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(duration_from_micros)]
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_micros(1_000_002);
+    ///
+    /// assert_eq!(1, duration.as_secs());
+    /// assert_eq!(2000, duration.subsec_nanos());
+    /// ```
+    #[unstable(feature = "duration_from_micros", issue = "44400")]
+    #[inline]
+    pub fn from_micros(micros: u64) -> Duration {
+        let secs = micros / MICROS_PER_SEC;
+        let nanos = ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO;
+        Duration { secs: secs, nanos: nanos }
+    }
+
     /// Returns the number of _whole_ seconds contained by this `Duration`.
     ///
     /// The returned value does not include the fractional (nanosecond) part of the
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 496be8b3eb2..0504e889ea1 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -538,11 +538,17 @@ pub enum BindingMode {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum RangeEnd {
-    Included,
+    Included(RangeSyntax),
     Excluded,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum RangeSyntax {
+    DotDotDot,
+    DotDotEq,
+}
+
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum PatKind {
     /// Represents a wildcard pattern (`_`)
     Wild,
@@ -578,7 +584,7 @@ pub enum PatKind {
     Ref(P<Pat>, Mutability),
     /// A literal
     Lit(P<Expr>),
-    /// A range pattern, e.g. `1...2` or `1..2`
+    /// A range pattern, e.g. `1...2`, `1..=2` or `1..2`
     Range(P<Expr>, P<Expr>, RangeEnd),
     /// `[a, b, ..i, y, z]` is represented as:
     ///     `PatKind::Slice(box [a, b], Some(i), box [y, z])`
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index b29883670bd..c3cf4747835 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -291,7 +291,7 @@ Erroneous code example:
 
 fn main() {
     let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
-    let x = &tmp[1...]; // error: inclusive range was used with no end
+    let x = &tmp[1..=]; // error: inclusive range was used with no end
 }
 ```
 
@@ -312,7 +312,7 @@ Or put an end to your inclusive range:
 
 fn main() {
     let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
-    let x = &tmp[1...3]; // ok!
+    let x = &tmp[1..=3]; // ok!
 }
 ```
 "##,
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index c139cfeaebf..0e05cce35e2 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -783,6 +783,10 @@ impl<'a> ExtCtxt<'a> {
     pub fn span_err(&self, sp: Span, msg: &str) {
         self.parse_sess.span_diagnostic.span_err(sp, msg);
     }
+    pub fn mut_span_err(&self, sp: Span, msg: &str)
+                        -> DiagnosticBuilder<'a> {
+        self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
+    }
     pub fn span_warn(&self, sp: Span, msg: &str) {
         self.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index de9c085cc78..6e7a8203b61 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -282,7 +282,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     let expansion = self.expand_invoc(invoc, ext);
                     self.collect_invocations(expansion, &[])
                 } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
-                    let item = item
+                    let derive_allowed = match item {
+                        Annotatable::Item(ref item) => match item.node {
+                            ast::ItemKind::Struct(..) |
+                            ast::ItemKind::Enum(..) |
+                            ast::ItemKind::Union(..) => true,
+                            _ => false,
+                        },
+                        _ => false,
+                    };
+                    if !derive_allowed {
+                        let attr = item.attrs().iter()
+                            .find(|attr| attr.check_name("derive"))
+                            .expect("`derive` attribute should exist");
+                        let span = attr.span;
+                        let mut err = self.cx.mut_span_err(span,
+                                                           "`derive` may only be applied to \
+                                                            structs, enums and unions");
+                        if let ast::AttrStyle::Inner = attr.style {
+                            let trait_list = traits.iter()
+                                .map(|t| format!("{}", t)).collect::<Vec<_>>();
+                            let suggestion = format!("#[derive({})]", trait_list.join(", "));
+                            err.span_suggestion(span, "try an outer attribute", suggestion);
+                        }
+                        err.emit();
+                    }
+
+                    let item = self.fully_configure(item)
                         .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
                     let item_with_markers =
                         add_derived_markers(&mut self.cx, item.span(), &traits, item.clone());
@@ -374,6 +400,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         result
     }
 
+    fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
+        let mut cfg = StripUnconfigured {
+            should_test: self.cx.ecfg.should_test,
+            sess: self.cx.parse_sess,
+            features: self.cx.ecfg.features,
+        };
+        // Since the item itself has already been configured by the InvocationCollector,
+        // we know that fold result vector will contain exactly one element
+        match item {
+            Annotatable::Item(item) => {
+                Annotatable::Item(cfg.fold_item(item).pop().unwrap())
+            }
+            Annotatable::TraitItem(item) => {
+                Annotatable::TraitItem(item.map(|item| cfg.fold_trait_item(item).pop().unwrap()))
+            }
+            Annotatable::ImplItem(item) => {
+                Annotatable::ImplItem(item.map(|item| cfg.fold_impl_item(item).pop().unwrap()))
+            }
+        }
+    }
+
     fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
         let result = match invoc.kind {
             InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
@@ -714,15 +761,6 @@ struct InvocationCollector<'a, 'b: 'a> {
     monotonic: bool,
 }
 
-macro_rules! fully_configure {
-    ($this:ident, $node:ident, $noop_fold:ident) => {
-        match $noop_fold($node, &mut $this.cfg).pop() {
-            Some(node) => node,
-            None => return SmallVector::new(),
-        }
-    }
-}
-
 impl<'a, 'b> InvocationCollector<'a, 'b> {
     fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
         let mark = Mark::fresh(self.cx.current_expansion.mark);
@@ -748,13 +786,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     item: Annotatable,
                     kind: ExpansionKind)
                     -> Expansion {
-        if !traits.is_empty() &&
-           (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) {
-            self.cx.span_err(traits[0].span, "`derive` can be only be applied to items");
-            self.cx.trace_macros_diag();
-            return kind.expect_from_annotatables(::std::iter::once(item));
-        }
-        self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item })
+        self.collect(kind, InvocationKind::Attr { attr, traits, item })
     }
 
     // If `item` is an attr invocation, remove and return the macro attribute.
@@ -880,7 +912,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
         let (attr, traits, mut item) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::Item(fully_configure!(self, item, noop_fold_item));
+            let item = Annotatable::Item(item);
             return self.collect_attr(attr, traits, item, ExpansionKind::Items).make_items();
         }
 
@@ -954,8 +986,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
         let (attr, traits, item) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item =
-                Annotatable::TraitItem(P(fully_configure!(self, item, noop_fold_trait_item)));
+            let item = Annotatable::TraitItem(P(item));
             return self.collect_attr(attr, traits, item, ExpansionKind::TraitItems)
                 .make_trait_items()
         }
@@ -975,7 +1006,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
         let (attr, traits, item) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
-            let item = Annotatable::ImplItem(P(fully_configure!(self, item, noop_fold_impl_item)));
+            let item = Annotatable::ImplItem(P(item));
             return self.collect_attr(attr, traits, item, ExpansionKind::ImplItems)
                 .make_impl_items();
         }
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c3f3a59c302..bd8c9a0ed40 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -686,7 +686,9 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
         token::At           => "At",
         token::Dot          => "Dot",
         token::DotDot       => "DotDot",
+        token::DotEq        => "DotEq",
         token::DotDotDot    => "DotDotDot",
+        token::DotDotEq     => "DotDotEq",
         token::Comma        => "Comma",
         token::Semi         => "Semi",
         token::Colon        => "Colon",
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 6560943a932..e92a7484f33 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -26,7 +26,7 @@ use self::AttributeType::*;
 use self::AttributeGate::*;
 
 use abi::Abi;
-use ast::{self, NodeId, PatKind, RangeEnd};
+use ast::{self, NodeId, PatKind, RangeEnd, RangeSyntax};
 use attr;
 use codemap::Spanned;
 use syntax_pos::Span;
@@ -261,7 +261,7 @@ declare_features! (
     // rustc internal
     (active, abi_vectorcall, "1.7.0", None),
 
-    // a...b and ...b
+    // a..=b and ..=b
     (active, inclusive_range_syntax, "1.7.0", Some(28237)),
 
     // X..Y patterns
@@ -380,7 +380,7 @@ declare_features! (
     // #[doc(masked)]
     (active, doc_masked, "1.21.0", None),
 
-    // allow `#[must_use]` on functions (RFC 1940)
+    // allow `#[must_use]` on functions and comparison operators (RFC 1940)
     (active, fn_must_use, "1.21.0", Some(43302)),
 
     // allow '|' at beginning of match arms (RFC 1925)
@@ -389,6 +389,12 @@ declare_features! (
     // Copy/Clone closures (RFC 2132)
     (active, clone_closures, "1.22.0", Some(44490)),
     (active, copy_closures, "1.22.0", Some(44490)),
+
+    // allow `'_` placeholder lifetimes
+    (active, underscore_lifetimes, "1.22.0", Some(44524)),
+
+    // allow `..=` in patterns (RFC 1192)
+    (active, dotdoteq_in_patterns, "1.22.0", Some(28237)),
 );
 
 declare_features! (
@@ -721,6 +727,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                                        is just used for rustc unit tests \
                                                        and will never be stable",
                                                       cfg_fn!(rustc_attrs))),
+    ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
+                                                      "rustc_attrs",
+                                                      "this attribute \
+                                                       is just used for rustc unit tests \
+                                                       and will never be stable",
+                                                      cfg_fn!(rustc_attrs))),
     ("rustc_symbol_name", Whitelisted, Gated(Stability::Unstable,
                                              "rustc_attrs",
                                              "internal rustc attributes will never be stable",
@@ -1488,6 +1500,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
                                    "exclusive range pattern syntax is experimental");
             }
+            PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotEq)) => {
+                gate_feature_post!(&self, dotdoteq_in_patterns, pattern.span,
+                                   "`..=` syntax in patterns is experimental");
+            }
             _ => {}
         }
         visit::walk_pat(self, pattern)
@@ -1572,6 +1588,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         }
         visit::walk_lifetime_def(self, lifetime_def)
     }
+
+    fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
+        if lt.ident.name == "'_" {
+            gate_feature_post!(&self, underscore_lifetimes, lt.span,
+                               "underscore lifetimes are unstable");
+        }
+        visit::walk_lifetime(self, lt)
+    }
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index ce3f16d2ba1..1cb7b0eca58 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1131,6 +1131,9 @@ impl<'a> StringReader<'a> {
                     if self.ch_is('.') {
                         self.bump();
                         Ok(token::DotDotDot)
+                    } else if self.ch_is('=') {
+                        self.bump();
+                        Ok(token::DotDotEq)
                     } else {
                         Ok(token::DotDot)
                     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a2514a04254..d5ba4b54d90 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use ast::{BinOpKind, UnOp};
-use ast::RangeEnd;
+use ast::{RangeEnd, RangeSyntax};
 use {ast, attr};
 use codemap::{self, CodeMap, Spanned, respan};
 use syntax_pos::{self, Span, BytePos};
@@ -432,7 +432,7 @@ impl Error {
             Error::InclusiveRangeWithNoEnd => {
                 let mut err = struct_span_err!(handler, sp, E0586,
                                                "inclusive range with no end");
-                err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)");
+                err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
                 err
             }
         }
@@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (span, self.mk_unary(UnOp::Not, e))
+                (lo.to(span), self.mk_unary(UnOp::Not, e))
             }
             // Suggest `!` for bitwise negation when encountering a `~`
             token::Tilde => {
@@ -2645,26 +2645,26 @@ impl<'a> Parser<'a> {
                 err.span_label(span_of_tilde, "did you mean `!`?");
                 err.help("use `!` instead of `~` if you meant to perform bitwise negation");
                 err.emit();
-                (span, self.mk_unary(UnOp::Not, e))
+                (lo.to(span), self.mk_unary(UnOp::Not, e))
             }
             token::BinOp(token::Minus) => {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (span, self.mk_unary(UnOp::Neg, e))
+                (lo.to(span), self.mk_unary(UnOp::Neg, e))
             }
             token::BinOp(token::Star) => {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (span, self.mk_unary(UnOp::Deref, e))
+                (lo.to(span), self.mk_unary(UnOp::Deref, e))
             }
             token::BinOp(token::And) | token::AndAnd => {
                 self.expect_and()?;
                 let m = self.parse_mutability();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (span, ExprKind::AddrOf(m, e))
+                (lo.to(span), ExprKind::AddrOf(m, e))
             }
             token::Ident(..) if self.token.is_keyword(keywords::In) => {
                 self.bump();
@@ -2675,13 +2675,13 @@ impl<'a> Parser<'a> {
                 let blk = self.parse_block()?;
                 let span = blk.span;
                 let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new());
-                (span, ExprKind::InPlace(place, blk_expr))
+                (lo.to(span), ExprKind::InPlace(place, blk_expr))
             }
             token::Ident(..) if self.token.is_keyword(keywords::Box) => {
                 self.bump();
                 let e = self.parse_prefix_expr(None);
                 let (span, e) = self.interpolated_or_expr_span(e)?;
-                (span, ExprKind::Box(e))
+                (lo.to(span), ExprKind::Box(e))
             }
             _ => return self.parse_dot_or_call_expr(Some(attrs))
         };
@@ -2710,7 +2710,7 @@ impl<'a> Parser<'a> {
                 LhsExpr::AttributesParsed(attrs) => Some(attrs),
                 _ => None,
             };
-            if self.token == token::DotDot || self.token == token::DotDotDot {
+            if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) {
                 return self.parse_prefix_range_expr(attrs);
             } else {
                 self.parse_prefix_expr(attrs)?
@@ -2744,6 +2744,10 @@ impl<'a> Parser<'a> {
             if op.precedence() < min_prec {
                 break;
             }
+            // Warn about deprecated ... syntax (until SNAP)
+            if self.token == token::DotDotDot {
+                self.warn_dotdoteq(self.span);
+            }
             self.bump();
             if op.is_comparison() {
                 self.check_no_chained_comparison(&lhs, &op);
@@ -2770,12 +2774,13 @@ impl<'a> Parser<'a> {
                     }
                 };
                 continue
-            } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
-                // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to
+            } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
+                // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
                 // generalise it to the Fixity::None code.
                 //
-                // We have 2 alternatives here: `x..y`/`x...y` and `x..`/`x...` The other
+                // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
                 // two variants are handled with `parse_prefix_range_expr` call above.
+                // (and `x...y`/`x...` until SNAP)
                 let rhs = if self.is_at_start_of_range_notation_rhs() {
                     Some(self.parse_assoc_expr_with(op.precedence() + 1,
                                                     LhsExpr::NotYetParsed)?)
@@ -2852,8 +2857,8 @@ impl<'a> Parser<'a> {
                     let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
                     self.mk_expr(span, aopexpr, ThinVec::new())
                 }
-                AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
-                    self.bug("As, Colon, DotDot or DotDotDot branch reached")
+                AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => {
+                    self.bug("AssocOp should have been handled by special case")
                 }
             };
 
@@ -2949,17 +2954,22 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr`
+    /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` (and `...expr` until SNAP)
     fn parse_prefix_range_expr(&mut self,
                                already_parsed_attrs: Option<ThinVec<Attribute>>)
                                -> PResult<'a, P<Expr>> {
-        debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot,
-                      "parse_prefix_range_expr: token {:?} is not DotDot or DotDotDot",
+        // SNAP remove DotDotDot
+        debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token),
+                      "parse_prefix_range_expr: token {:?} is not DotDot/DotDotDot/DotDotEq",
                       self.token);
         let tok = self.token.clone();
         let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
         let lo = self.span;
         let mut hi = self.span;
+        // Warn about deprecated ... syntax (until SNAP)
+        if tok == token::DotDotDot {
+            self.warn_dotdoteq(self.span);
+        }
         self.bump();
         let opt_end = if self.is_at_start_of_range_notation_rhs() {
             // RHS must be parsed with more associativity than the dots.
@@ -3450,7 +3460,7 @@ impl<'a> Parser<'a> {
     fn parse_as_ident(&mut self) -> bool {
         self.look_ahead(1, |t| match *t {
             token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
-            token::DotDotDot | token::ModSep | token::Not => Some(false),
+            token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false),
             // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the
             // range pattern branch
             token::DotDot => None,
@@ -3544,11 +3554,13 @@ impl<'a> Parser<'a> {
                         let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
                         pat = PatKind::Mac(mac);
                     }
-                    token::DotDotDot | token::DotDot => {
+                    token::DotDotDot | token::DotDotEq | token::DotDot => {
                         let end_kind = match self.token {
                             token::DotDot => RangeEnd::Excluded,
-                            token::DotDotDot => RangeEnd::Included,
-                            _ => panic!("can only parse `..` or `...` for ranges (checked above)"),
+                            token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot),
+                            token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq),
+                            _ => panic!("can only parse `..`/`...`/`..=` for ranges \
+                                         (checked above)"),
                         };
                         // Parse range
                         let span = lo.to(self.prev_span);
@@ -3589,7 +3601,12 @@ impl<'a> Parser<'a> {
                     Ok(begin) => {
                         if self.eat(&token::DotDotDot) {
                             let end = self.parse_pat_range_end()?;
-                            pat = PatKind::Range(begin, end, RangeEnd::Included);
+                            pat = PatKind::Range(begin, end,
+                                    RangeEnd::Included(RangeSyntax::DotDotDot));
+                        } else if self.eat(&token::DotDotEq) {
+                            let end = self.parse_pat_range_end()?;
+                            pat = PatKind::Range(begin, end,
+                                    RangeEnd::Included(RangeSyntax::DotDotEq));
                         } else if self.eat(&token::DotDot) {
                             let end = self.parse_pat_range_end()?;
                             pat = PatKind::Range(begin, end, RangeEnd::Excluded);
@@ -3973,7 +3990,7 @@ impl<'a> Parser<'a> {
                     token::BinOp(token::Minus) | token::BinOp(token::Star) |
                     token::BinOp(token::And) | token::BinOp(token::Or) |
                     token::AndAnd | token::OrOr |
-                    token::DotDot | token::DotDotDot => false,
+                    token::DotDot | token::DotDotDot | token::DotDotEq => false,
                     _ => true,
                 } {
                     self.warn_missing_semicolon();
@@ -4195,6 +4212,12 @@ impl<'a> Parser<'a> {
         }).emit();
     }
 
+    fn warn_dotdoteq(&self, span: Span) {
+        self.diagnostic().struct_span_warn(span, {
+            "`...` is being replaced by `..=`"
+        }).emit();
+    }
+
     // Parse bounds of a type parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
     // BOUND = TY_BOUND | LT_BOUND
     // LT_BOUND = LIFETIME (e.g. `'a`)
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index a316733bdb5..4888654fac9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -152,6 +152,8 @@ pub enum Token {
     Dot,
     DotDot,
     DotDotDot,
+    DotDotEq,
+    DotEq, // HACK(durka42) never produced by the parser, only used for libproc_macro
     Comma,
     Semi,
     Colon,
@@ -212,18 +214,19 @@ impl Token {
     pub fn can_begin_expr(&self) -> bool {
         match *self {
             Ident(ident)                => ident_can_begin_expr(ident), // value name or keyword
-            OpenDelim(..)               | // tuple, array or block
-            Literal(..)                 | // literal
-            Not                         | // operator not
-            BinOp(Minus)                | // unary minus
-            BinOp(Star)                 | // dereference
-            BinOp(Or) | OrOr            | // closure
-            BinOp(And)                  | // reference
-            AndAnd                      | // double reference
-            DotDot | DotDotDot          | // range notation
-            Lt | BinOp(Shl)             | // associated path
-            ModSep                      | // global path
-            Pound                       => true, // expression attributes
+            OpenDelim(..)                     | // tuple, array or block
+            Literal(..)                       | // literal
+            Not                               | // operator not
+            BinOp(Minus)                      | // unary minus
+            BinOp(Star)                       | // dereference
+            BinOp(Or) | OrOr                  | // closure
+            BinOp(And)                        | // reference
+            AndAnd                            | // double reference
+            DotDot | DotDotDot | DotDotEq     | // range notation
+                // SNAP remove DotDotDot
+            Lt | BinOp(Shl)                   | // associated path
+            ModSep                            | // global path
+            Pound                             => true, // expression attributes
             Interpolated(ref nt) => match nt.0 {
                 NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true,
                 _ => false,
@@ -402,10 +405,12 @@ impl Token {
             Dot => match joint {
                 Dot => DotDot,
                 DotDot => DotDotDot,
+                DotEq => DotDotEq,
                 _ => return None,
             },
             DotDot => match joint {
                 Dot => DotDotDot,
+                Eq => DotDotEq,
                 _ => return None,
             },
             Colon => match joint {
@@ -413,9 +418,9 @@ impl Token {
                 _ => return None,
             },
 
-            Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | Comma |
-            Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question |
-            OpenDelim(..) | CloseDelim(..) | Underscore => return None,
+            Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot | DotEq |
+            DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
+            Question | OpenDelim(..) | CloseDelim(..) | Underscore => return None,
 
             Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
             Whitespace | Comment | Shebang(..) | Eof => return None,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9903dc50f36..959dd4ef30f 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -11,7 +11,7 @@
 pub use self::AnnNode::*;
 
 use abi::{self, Abi};
-use ast::{self, BlockCheckMode, PatKind, RangeEnd};
+use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
 use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::Attribute;
 use util::parser::{self, AssocOp, Fixity};
@@ -203,6 +203,8 @@ pub fn token_to_string(tok: &Token) -> String {
         token::Dot                  => ".".to_string(),
         token::DotDot               => "..".to_string(),
         token::DotDotDot            => "...".to_string(),
+        token::DotDotEq             => "..=".to_string(),
+        token::DotEq                => ".=".to_string(),
         token::Comma                => ",".to_string(),
         token::Semi                 => ";".to_string(),
         token::Colon                => ":".to_string(),
@@ -2588,7 +2590,8 @@ impl<'a> State<'a> {
                 self.print_expr(begin)?;
                 self.s.space()?;
                 match *end_kind {
-                    RangeEnd::Included => self.s.word("...")?,
+                    RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("...")?,
+                    RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..=")?,
                     RangeEnd::Excluded => self.s.word("..")?,
                 }
                 self.print_expr(end)?;
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index a4f06cb1b45..590874806d7 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -62,8 +62,8 @@ pub enum AssocOp {
     As,
     /// `..` range
     DotDot,
-    /// `...` range
-    DotDotDot,
+    /// `..=` range
+    DotDotEq,
     /// `:`
     Colon,
 }
@@ -105,7 +105,8 @@ impl AssocOp {
             Token::AndAnd => Some(LAnd),
             Token::OrOr => Some(LOr),
             Token::DotDot => Some(DotDot),
-            Token::DotDotDot => Some(DotDotDot),
+            Token::DotDotEq => Some(DotDotEq),
+            Token::DotDotDot => Some(DotDotEq), // remove this after SNAP
             Token::Colon => Some(Colon),
             _ if t.is_keyword(keywords::As) => Some(As),
             _ => None
@@ -151,7 +152,7 @@ impl AssocOp {
             Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => 7,
             LAnd => 6,
             LOr => 5,
-            DotDot | DotDotDot => 4,
+            DotDot | DotDotEq => 4,
             Inplace => 3,
             Assign | AssignOp(_) => 2,
         }
@@ -166,7 +167,7 @@ impl AssocOp {
             As | Multiply | Divide | Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd |
             BitXor | BitOr | Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual |
             LAnd | LOr | Colon => Fixity::Left,
-            DotDot | DotDotDot => Fixity::None
+            DotDot | DotDotEq => Fixity::None
         }
     }
 
@@ -176,7 +177,7 @@ impl AssocOp {
             Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual => true,
             Inplace | Assign | AssignOp(_) | As | Multiply | Divide | Modulus | Add | Subtract |
             ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd | LOr |
-            DotDot | DotDotDot | Colon => false
+            DotDot | DotDotEq | Colon => false
         }
     }
 
@@ -186,7 +187,7 @@ impl AssocOp {
             Assign | AssignOp(_) | Inplace => true,
             Less | Greater | LessEqual | GreaterEqual | Equal | NotEqual | As | Multiply | Divide |
             Modulus | Add | Subtract | ShiftLeft | ShiftRight | BitAnd | BitXor | BitOr | LAnd |
-            LOr | DotDot | DotDotDot | Colon => false
+            LOr | DotDot | DotDotEq | Colon => false
         }
     }
 
@@ -211,7 +212,7 @@ impl AssocOp {
             BitOr => Some(BinOpKind::BitOr),
             LAnd => Some(BinOpKind::And),
             LOr => Some(BinOpKind::Or),
-            Inplace | Assign | AssignOp(_) | As | DotDot | DotDotDot | Colon => None
+            Inplace | Assign | AssignOp(_) | As | DotDot | DotDotEq | Colon => None
         }
     }
 }
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index d701810e2e9..5c1ca19d635 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -428,8 +428,9 @@ impl<'a> TraitDef<'a> {
                         }
                     }
                     _ => {
-                        cx.span_err(mitem.span,
-                                    "`derive` may only be applied to structs, enums and unions");
+                        // Non-ADT derive is an error, but it should have been
+                        // set earlier; see
+                        // libsyntax/ext/expand.rs:MacroExpander::expand()
                         return;
                     }
                 };
@@ -448,8 +449,10 @@ impl<'a> TraitDef<'a> {
                 push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
             }
             _ => {
-                cx.span_err(mitem.span,
-                            "`derive` may only be applied to structs and enums");
+                // Non-Item derive is an error, but it should have been
+                // set earlier; see
+                // libsyntax/ext/expand.rs:MacroExpander::expand()
+                return;
             }
         }
     }
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 919804d7efd..4790fa0a7ed 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -25,7 +25,7 @@ use std::fmt;
 
 /// A SyntaxContext represents a chain of macro expansions (represented by marks).
 #[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
-pub struct SyntaxContext(u32);
+pub struct SyntaxContext(pub(super) u32);
 
 #[derive(Copy, Clone, Default)]
 pub struct SyntaxContextData {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 27fbca19dcc..582f2798181 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -25,11 +25,10 @@
 #![feature(optin_builtin_traits)]
 #![allow(unused_attributes)]
 #![feature(specialization)]
-#![feature(staged_api)]
 
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
-use std::cmp;
+use std::cmp::{self, Ordering};
 use std::fmt;
 use std::hash::Hasher;
 use std::ops::{Add, Sub};
@@ -47,6 +46,9 @@ extern crate serialize as rustc_serialize; // used by deriving
 pub mod hygiene;
 pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
 
+mod span_encoding;
+pub use span_encoding::{Span, DUMMY_SP};
+
 pub mod symbol;
 
 pub type FileName = String;
@@ -59,23 +61,33 @@ pub type FileName = String;
 /// able to use many of the functions on spans in codemap and you cannot assume
 /// that the length of the span = hi - lo; there may be space in the BytePos
 /// range between files.
+///
+/// `SpanData` is public because `Span` uses a thread-local interner and can't be
+/// sent to other threads, but some pieces of performance infra run in a separate thread.
+/// Using `Span` is generally preferred.
 #[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)]
-pub struct Span {
-    #[unstable(feature = "rustc_private", issue = "27812")]
-    #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")]
+pub struct SpanData {
     pub lo: BytePos,
-    #[unstable(feature = "rustc_private", issue = "27812")]
-    #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")]
     pub hi: BytePos,
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
-    #[unstable(feature = "rustc_private", issue = "27812")]
-    #[rustc_deprecated(since = "1.21", reason = "use getters/setters instead")]
     pub ctxt: SyntaxContext,
 }
 
-#[allow(deprecated)]
-pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), ctxt: NO_EXPANSION };
+// The interner in thread-local, so `Span` shouldn't move between threads.
+impl !Send for Span {}
+impl !Sync for Span {}
+
+impl PartialOrd for Span {
+    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
+        PartialOrd::partial_cmp(&self.data(), &rhs.data())
+    }
+}
+impl Ord for Span {
+    fn cmp(&self, rhs: &Self) -> Ordering {
+        Ord::cmp(&self.data(), &rhs.data())
+    }
+}
 
 /// A collection of spans. Spans have two orthogonal attributes:
 ///
@@ -90,38 +102,32 @@ pub struct MultiSpan {
 }
 
 impl Span {
-    #[allow(deprecated)]
-    #[inline]
-    pub fn new(lo: BytePos, hi: BytePos, ctxt: SyntaxContext) -> Self {
-        if lo <= hi { Span { lo, hi, ctxt } } else { Span { lo: hi, hi: lo, ctxt } }
-    }
-
-    #[allow(deprecated)]
     #[inline]
     pub fn lo(self) -> BytePos {
-        self.lo
+        self.data().lo
     }
     #[inline]
     pub fn with_lo(self, lo: BytePos) -> Span {
-        Span::new(lo, self.hi(), self.ctxt())
+        let base = self.data();
+        Span::new(lo, base.hi, base.ctxt)
     }
-    #[allow(deprecated)]
     #[inline]
     pub fn hi(self) -> BytePos {
-        self.hi
+        self.data().hi
     }
     #[inline]
     pub fn with_hi(self, hi: BytePos) -> Span {
-        Span::new(self.lo(), hi, self.ctxt())
+        let base = self.data();
+        Span::new(base.lo, hi, base.ctxt)
     }
-    #[allow(deprecated)]
     #[inline]
     pub fn ctxt(self) -> SyntaxContext {
-        self.ctxt
+        self.data().ctxt
     }
     #[inline]
     pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
-        Span::new(self.lo(), self.hi(), ctxt)
+        let base = self.data();
+        Span::new(base.lo, base.hi, ctxt)
     }
 
     /// Returns a new span representing just the end-point of this span
@@ -342,6 +348,12 @@ impl fmt::Debug for Span {
     }
 }
 
+impl fmt::Debug for SpanData {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        SPAN_DEBUG.with(|span_debug| span_debug.get()(Span::new(self.lo, self.hi, self.ctxt), f))
+    }
+}
+
 impl MultiSpan {
     pub fn new() -> MultiSpan {
         MultiSpan {
diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs
new file mode 100644
index 00000000000..c2b32171a9a
--- /dev/null
+++ b/src/libsyntax_pos/span_encoding.rs
@@ -0,0 +1,143 @@
+// 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.
+
+// Spans are encoded using 1-bit tag and 2 different encoding formats (one for each tag value).
+// One format is used for keeping span data inline,
+// another contains index into an out-of-line span interner.
+// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
+// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
+
+use {BytePos, SpanData};
+use hygiene::SyntaxContext;
+
+use rustc_data_structures::fx::FxHashMap;
+use std::cell::RefCell;
+
+/// A compressed span.
+/// Contains either fields of `SpanData` inline if they are small, or index into span interner.
+/// The primary goal of `Span` is to be as small as possible and fit into other structures
+/// (that's why it uses `packed` as well). Decoding speed is the second priority.
+/// See `SpanData` for the info on span fields in decoded representation.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[repr(packed)]
+pub struct Span(u32);
+
+/// Dummy span, both position and length are zero, syntax context is zero as well.
+/// This span is kept inline and encoded with format 0.
+pub const DUMMY_SP: Span = Span(0);
+
+impl Span {
+    #[inline]
+    pub fn new(lo: BytePos, hi: BytePos, ctxt: SyntaxContext) -> Self {
+        encode(&match lo <= hi {
+            true => SpanData { lo, hi, ctxt },
+            false => SpanData { lo: hi, hi: lo, ctxt },
+        })
+    }
+
+    #[inline]
+    pub fn data(self) -> SpanData {
+        decode(self)
+    }
+}
+
+// Tags
+const TAG_INLINE: u32 = 0;
+const TAG_INTERNED: u32 = 1;
+const TAG_MASK: u32 = 1;
+
+// Fields indexes
+const BASE_INDEX: usize = 0;
+const LEN_INDEX: usize = 1;
+const CTXT_INDEX: usize = 2;
+
+// Tag = 0, inline format.
+// -----------------------------------
+// | base 31:8  | len 7:1  | tag 0:0 |
+// -----------------------------------
+const INLINE_SIZES: [u32; 3] = [24, 7, 0];
+const INLINE_OFFSETS: [u32; 3] = [8, 1, 1];
+
+// Tag = 1, interned format.
+// ------------------------
+// | index 31:1 | tag 0:0 |
+// ------------------------
+const INTERNED_INDEX_SIZE: u32 = 31;
+const INTERNED_INDEX_OFFSET: u32 = 1;
+
+#[inline]
+fn encode(sd: &SpanData) -> Span {
+    let (base, len, ctxt) = (sd.lo.0, sd.hi.0 - sd.lo.0, sd.ctxt.0);
+
+    let val = if (base >> INLINE_SIZES[BASE_INDEX]) == 0 &&
+                 (len >> INLINE_SIZES[LEN_INDEX]) == 0 &&
+                 (ctxt >> INLINE_SIZES[CTXT_INDEX]) == 0 {
+        (base << INLINE_OFFSETS[BASE_INDEX]) | (len << INLINE_OFFSETS[LEN_INDEX]) |
+        (ctxt << INLINE_OFFSETS[CTXT_INDEX]) | TAG_INLINE
+    } else {
+        let index = with_span_interner(|interner| interner.intern(sd));
+        (index << INTERNED_INDEX_OFFSET) | TAG_INTERNED
+    };
+    Span(val)
+}
+
+#[inline]
+fn decode(span: Span) -> SpanData {
+    let val = span.0;
+
+    // Extract a field at position `pos` having size `size`.
+    let extract = |pos: u32, size: u32| {
+        let mask = ((!0u32) as u64 >> (32 - size)) as u32; // Can't shift u32 by 32
+        (val >> pos) & mask
+    };
+
+    let (base, len, ctxt) = if val & TAG_MASK == TAG_INLINE {(
+        extract(INLINE_OFFSETS[BASE_INDEX], INLINE_SIZES[BASE_INDEX]),
+        extract(INLINE_OFFSETS[LEN_INDEX], INLINE_SIZES[LEN_INDEX]),
+        extract(INLINE_OFFSETS[CTXT_INDEX], INLINE_SIZES[CTXT_INDEX]),
+    )} else {
+        let index = extract(INTERNED_INDEX_OFFSET, INTERNED_INDEX_SIZE);
+        return with_span_interner(|interner| *interner.get(index));
+    };
+    SpanData { lo: BytePos(base), hi: BytePos(base + len), ctxt: SyntaxContext(ctxt) }
+}
+
+#[derive(Default)]
+struct SpanInterner {
+    spans: FxHashMap<SpanData, u32>,
+    span_data: Vec<SpanData>,
+}
+
+impl SpanInterner {
+    fn intern(&mut self, span_data: &SpanData) -> u32 {
+        if let Some(index) = self.spans.get(span_data) {
+            return *index;
+        }
+
+        let index = self.spans.len() as u32;
+        self.span_data.push(*span_data);
+        self.spans.insert(*span_data, index);
+        index
+    }
+
+    #[inline]
+    fn get(&self, index: u32) -> &SpanData {
+        &self.span_data[index as usize]
+    }
+}
+
+// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
+#[inline]
+fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T {
+    thread_local!(static INTERNER: RefCell<SpanInterner> = {
+        RefCell::new(SpanInterner::default())
+    });
+    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
+}
diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs
index 335817fddbb..8733c7436d5 100644
--- a/src/rtstartup/rsbegin.rs
+++ b/src/rtstartup/rsbegin.rs
@@ -38,7 +38,7 @@ trait Copy {}
 trait Freeze {}
 impl Freeze for .. {}
 
-#[lang="drop_in_place"]
+#[lang = "drop_in_place"]
 #[inline]
 #[allow(unconditional_recursion)]
 pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
diff --git a/src/rtstartup/rsend.rs b/src/rtstartup/rsend.rs
index 9229b4e3128..a6aed3540dd 100644
--- a/src/rtstartup/rsend.rs
+++ b/src/rtstartup/rsend.rs
@@ -25,7 +25,7 @@ trait Copy {}
 trait Freeze {}
 impl Freeze for .. {}
 
-#[lang="drop_in_place"]
+#[lang = "drop_in_place"]
 #[inline]
 #[allow(unconditional_recursion)]
 pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml
index 39df3528be3..0c04402124a 100644
--- a/src/rustc/libc_shim/Cargo.toml
+++ b/src/rustc/libc_shim/Cargo.toml
@@ -1,16 +1,7 @@
-# This is a shim Cargo.toml over the "real Cargo.toml" found in the libc
-# repository itself. The purpose for this is to add a build script which prints
-# out `--cfg stdbuild` to mirror the makefiles' build system.
-#
-# Note that other than that this isn't actually needed, and we should probably
-# remove this shim in favor of just working with cargo features directly with
-# libc. That should make everything nicer!
-
 [package]
 name = "libc"
 version = "0.0.0"
 authors = ["The Rust Project Developers"]
-build = "build.rs"
 
 [lib]
 name = "libc"
@@ -20,4 +11,27 @@ bench = false
 doc = false
 
 [dependencies]
+# Specify the path to libcore; at the time of writing, removing this shim in
+# favor of using libc from git results in a compilation failure:
+#
+# Building stage0 std artifacts (x86_64-apple-darwin -> x86_64-apple-darwin)
+#    Compiling libc v0.0.0 (file:///Users/tamird/src/rust/src/rustc/libc_shim)
+# error[E0463]: can't find crate for `core`
+#
+# error: aborting due to previous error
+#
+# error: Could not compile `libc`.
+#
+# Caused by:
+#   process didn't exit successfully: `/Users/tamird/src/rust/build/bootstrap/debug/rustc --crate-name libc src/rustc/libc_shim/../../liblibc/src/lib.rs --error-format json --crate-type lib --emit=dep-info,link -C opt-level=2 --cfg feature="default" --cfg feature="no_std" --cfg feature="stdbuild" -C metadata=d758f87058112d7d -C extra-filename=-d758f87058112d7d --out-dir /Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps --target x86_64-apple-darwin -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/x86_64-apple-darwin/release/deps -L dependency=/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0-std/release/deps` (exit code: 101)
+# thread 'main' panicked at 'command did not execute successfully: "/Users/tamird/src/rust/build/x86_64-apple-darwin/stage0/bin/cargo" "build" "-j" "4" "--target" "x86_64-apple-darwin" "--release" "--features" "panic-unwind jemalloc backtrace" "--manifest-path" "/Users/tamird/src/rust/src/libstd/Cargo.toml" "--message-format" "json"
+# expected success, got: exit code: 101', src/bootstrap/compile.rs:883:8
+#
+# See https://github.com/rust-lang/rfcs/pull/1133.
 core = { path = "../../libcore" }
+
+[features]
+# Certain parts of libc are conditionally compiled differently than when used
+# outside rustc. See https://github.com/rust-lang/libc/search?l=Rust&q=stdbuild&type=&utf8=%E2%9C%93.
+stdbuild = []
+default = ["stdbuild"]
diff --git a/src/test/compile-fail/E0506.rs b/src/test/compile-fail/E0506.rs
index ddaffd4a273..b2cf66849c7 100644
--- a/src/test/compile-fail/E0506.rs
+++ b/src/test/compile-fail/E0506.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 struct FancyNum {
     num: u8,
 }
@@ -15,7 +18,9 @@ struct FancyNum {
 fn main() {
     let mut fancy_num = FancyNum { num: 5 };
     let fancy_ref = &fancy_num;
-    fancy_num = FancyNum { num: 6 }; //~ ERROR E0506
+    fancy_num = FancyNum { num: 6 }; //[ast]~ ERROR E0506
+                                     //[mir]~^ ERROR (Mir) [E0506]
+                                     //[mir]~| ERROR (Ast) [E0506]
 
     println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
 }
diff --git a/src/test/compile-fail/E0586.rs b/src/test/compile-fail/E0586.rs
index 0b063569abc..c1bfc5c73a1 100644
--- a/src/test/compile-fail/E0586.rs
+++ b/src/test/compile-fail/E0586.rs
@@ -10,5 +10,5 @@
 
 fn main() {
     let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1];
-    let x = &tmp[1...]; //~ ERROR E0586
+    let x = &tmp[1..=]; //~ ERROR E0586
 }
diff --git a/src/test/compile-fail/E0637.rs b/src/test/compile-fail/E0637.rs
new file mode 100644
index 00000000000..455529b088a
--- /dev/null
+++ b/src/test/compile-fail/E0637.rs
@@ -0,0 +1,20 @@
+// 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(underscore_lifetimes)]
+
+struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
+fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
+
+struct Bar<'a>(&'a u8);
+impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
+  fn bar() {}
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
index 802b83119b7..e63de3a3bed 100644
--- a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 struct point { x: isize, y: isize }
 
 fn a() {
@@ -17,7 +20,9 @@ fn a() {
     // This assignment is illegal because the field x is not
     // inherently mutable; since `p` was made immutable, `p.x` is now
     // immutable.  Otherwise the type of &_q.x (&isize) would be wrong.
-    p.x = 5; //~ ERROR cannot assign to `p.x`
+    p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
+             //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed (Ast)
+             //[mir]~| ERROR cannot assign to `p.0` because it is borrowed (Mir)
     q.x;
 }
 
@@ -27,7 +32,9 @@ fn c() {
 
     let mut p = point {x: 3, y: 4};
     let q = &p.y;
-    p = point {x: 5, y: 7};//~ ERROR cannot assign to `p`
+    p = point {x: 5, y: 7};//[ast]~ ERROR cannot assign to `p`
+                           //[mir]~^ ERROR cannot assign to `p` because it is borrowed (Ast)
+                           //[mir]~| ERROR cannot assign to `p` because it is borrowed (Mir)
     p.x; // silence warning
     *q; // stretch loan
 }
@@ -38,7 +45,9 @@ fn d() {
 
     let mut p = point {x: 3, y: 4};
     let q = &p.y;
-    p.y = 5; //~ ERROR cannot assign to `p.y`
+    p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
+             //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed (Ast)
+             //[mir]~| ERROR cannot assign to `p.1` because it is borrowed (Mir)
     *q;
 }
 
diff --git a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
index aaa07661215..6c003ec2d48 100644
--- a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
@@ -11,6 +11,10 @@
 // Tests that two closures cannot simultaneously have mutable
 // and immutable access to the variable. Issue #6801.
 
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 #![feature(box_syntax)]
 
 fn get(x: &isize) -> isize {
@@ -24,37 +28,49 @@ fn set(x: &mut isize) {
 fn a() {
     let mut x = 3;
     let c1 = || x = 4;
-    let c2 = || x * 5; //~ ERROR cannot borrow `x`
+    let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+                       //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast)
+                       //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir)
 }
 
 fn b() {
     let mut x = 3;
     let c1 = || set(&mut x);
-    let c2 = || get(&x); //~ ERROR cannot borrow `x`
+    let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
+                         //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast)
+                         //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir)
 }
 
 fn c() {
     let mut x = 3;
     let c1 = || set(&mut x);
-    let c2 = || x * 5; //~ ERROR cannot borrow `x`
+    let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
+                       //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Ast)
+                       //[mir]~| ERROR cannot borrow `x` as immutable because it is also borrowed as mutable (Mir)
 }
 
 fn d() {
     let mut x = 3;
     let c2 = || x * 5;
-    x = 5; //~ ERROR cannot assign
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast)
+           //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir)
 }
 
 fn e() {
     let mut x = 3;
     let c1 = || get(&x);
-    x = 5; //~ ERROR cannot assign
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast)
+           //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir)
 }
 
 fn f() {
     let mut x: Box<_> = box 3;
     let c1 = || get(&*x);
-    *x = 5; //~ ERROR cannot assign
+    *x = 5; //[ast]~ ERROR cannot assign
+            //[mir]~^ ERROR cannot assign to `*x` because it is borrowed (Ast)
+            //[mir]~| ERROR cannot assign to `(*x)` because it is borrowed (Mir)
 }
 
 fn g() {
@@ -64,7 +80,9 @@ fn g() {
 
     let mut x: Box<_> = box Foo { f: box 3 };
     let c1 = || get(&*x.f);
-    *x.f = 5; //~ ERROR cannot assign to `*x.f`
+    *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
+              //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed (Ast)
+              //[mir]~| ERROR cannot assign to `(*(*x).0)` because it is borrowed (Mir)
 }
 
 fn h() {
@@ -74,7 +92,9 @@ fn h() {
 
     let mut x: Box<_> = box Foo { f: box 3 };
     let c1 = || get(&*x.f);
-    let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable
+    let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
+                          //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable (Ast)
+                          //[mir]~| ERROR cannot borrow `x` as mutable because it is also borrowed as immutable (Mir)
 }
 
 fn main() {
diff --git a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
index 8af10231921..03b6b1d7324 100644
--- a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
+++ b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
@@ -8,11 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 fn main() {
     let mut _a = 3;
     let _b = &mut _a;
     {
         let _c = &*_b;
-        _a = 4; //~ ERROR cannot assign to `_a`
+        _a = 4; //[ast]~ ERROR cannot assign to `_a`
+                //[mir]~^ ERROR cannot assign to `_a` because it is borrowed (Ast)
+                //[mir]~| ERROR cannot assign to `_a` because it is borrowed (Mir)
     }
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
index f24e82d11c5..0e8c003e408 100644
--- a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
+++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 
@@ -22,7 +25,9 @@ fn separate_arms() {
             x = Some(0);
         }
         Some(ref __isize) => {
-            x = Some(1); //~ ERROR cannot assign
+            x = Some(1); //[ast]~ ERROR cannot assign
+                         //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast)
+                         //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir)
         }
     }
     x.clone(); // just to prevent liveness warnings
diff --git a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
index c219b7c5424..3639db5cfc4 100644
--- a/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
+++ b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Zemit-end-regions -Zborrowck-mir
+
 // Test that immutable pattern bindings cannot be reassigned.
 
 #![feature(slice_patterns)]
@@ -23,31 +26,41 @@ struct S {
 pub fn main() {
     match 1 {
         x => {
-            x += 1; //~ ERROR re-assignment of immutable variable `x`
+            x += 1; //[ast]~ ERROR re-assignment of immutable variable `x`
+                    //[mir]~^ ERROR (Mir) [E0384]
+                    //[mir]~| ERROR (Ast) [E0384]
         }
     }
 
     match E::Foo(1) {
         E::Foo(x) => {
-            x += 1; //~ ERROR re-assignment of immutable variable `x`
+            x += 1; //[ast]~ ERROR re-assignment of immutable variable `x`
+                    //[mir]~^ ERROR (Mir) [E0384]
+                    //[mir]~| ERROR (Ast) [E0384]
         }
     }
 
     match (S { bar: 1 }) {
         S { bar: x } => {
-            x += 1; //~ ERROR re-assignment of immutable variable `x`
+            x += 1; //[ast]~ ERROR re-assignment of immutable variable `x`
+                    //[mir]~^ ERROR (Mir) [E0384]
+                    //[mir]~| ERROR (Ast) [E0384]
         }
     }
 
     match (1,) {
         (x,) => {
-            x += 1; //~ ERROR re-assignment of immutable variable `x`
+            x += 1; //[ast]~ ERROR re-assignment of immutable variable `x`
+                    //[mir]~^ ERROR (Mir) [E0384]
+                    //[mir]~| ERROR (Ast) [E0384]
         }
     }
 
     match [1,2,3] {
         [x,_,_] => {
-            x += 1; //~ ERROR re-assignment of immutable variable `x`
+            x += 1; //[ast]~ ERROR re-assignment of immutable variable `x`
+                    //[mir]~^ ERROR (Mir) [E0384]
+                    //[mir]~| ERROR (Ast) [E0384]
         }
     }
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs
index 7284fa7a850..9a39ff6206b 100644
--- a/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 
-fn foo(x: *const Box<isize>) -> Box<isize> {
-    let y = *x; //~ ERROR dereference of raw pointer requires unsafe function or block
+unsafe fn foo(x: *const Box<isize>) -> Box<isize> {
+    let y = *x; //~ ERROR cannot move out of dereference of raw pointer
     return y;
 }
 
diff --git a/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
index bee56c9bf39..9b20cd470f6 100644
--- a/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
@@ -13,6 +13,9 @@
 // operator. The accounting of the all the implicit things going on
 // here is rather subtle. Issue #20232.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 use std::ops::{Deref, Index};
 
 struct MyVec<T> { x: T }
@@ -39,7 +42,9 @@ fn main() {
     let mut v = MyVec { x: MyPtr { x: Foo { f: 22 } } };
     let i = &v[0].f;
     v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
-    //~^ ERROR cannot assign to `v`
+    //[ast]~^ ERROR cannot assign to `v`
+    //[mir]~^^ ERROR cannot assign to `v` because it is borrowed (Ast)
+    //[mir]~| ERROR cannot assign to `v` because it is borrowed (Mir)
     read(*i);
 }
 
diff --git a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
index d176245823e..06bb98fa0ec 100644
--- a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
+++ b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 fn main() {
     let mut x: Option<isize> = None;
     match x {
@@ -17,7 +20,9 @@ fn main() {
       }
       Some(ref i) => {
           // But on this branch, `i` is an outstanding borrow
-          x = Some(*i+1); //~ ERROR cannot assign to `x`
+          x = Some(*i+1); //[ast]~ ERROR cannot assign to `x`
+                          //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast)
+                          //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir)
       }
     }
     x.clone(); // just to prevent liveness warnings
diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
index 20b882e1f80..73d323ea82c 100644
--- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
+++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
 
 #[derive(Clone, Copy)]
 union U {
@@ -30,11 +32,15 @@ fn main() {
         }
         {
             let ra = &u.a;
-            let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+            let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+                                //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Ast)
+                                //[mir]~| ERROR cannot borrow `u.0` as mutable because it is also borrowed as immutable (Mir)
         }
         {
             let ra = &u.a;
-            u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+            u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
+                     //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast)
+                     //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir)
         }
         // Imm borrow, other field
         {
@@ -47,45 +53,65 @@ fn main() {
         }
         {
             let ra = &u.a;
-            let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+            let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+                                //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) (Ast)
+                                // FIXME Error for MIR (needs support for union)
         }
         {
             let ra = &u.a;
-            u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+            u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
+                     //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed (Ast)
+                     // FIXME Error for MIR (needs support for union)
         }
         // Mut borrow, same field
         {
             let rma = &mut u.a;
-            let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+            let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+                         //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Ast)
+                         //[mir]~| ERROR cannot borrow `u.0` as immutable because it is also borrowed as mutable (Mir)
         }
         {
             let ra = &mut u.a;
-            let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
+            let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+                         //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
+                         //[mir]~| ERROR cannot use `u.0` because it was mutably borrowed (Mir)
         }
         {
             let rma = &mut u.a;
-            let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
+            let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
+                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time (Ast)
+                                 //[mir]~| ERROR cannot borrow `u.0` as mutable more than once at a time (Mir)
         }
         {
             let rma = &mut u.a;
-            u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+            u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
+                     //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast)
+                     //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir)
         }
         // Mut borrow, other field
         {
             let rma = &mut u.a;
-            let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+            let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+                           //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) (Ast)
+                           // FIXME Error for MIR (needs support for union)
         }
         {
             let ra = &mut u.a;
-            let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
+            let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
+                         //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed (Ast)
+                         // FIXME Error for MIR (needs support for union)
         }
         {
             let rma = &mut u.a;
-            let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
+            let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
+                                 //[mir]~^ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time (Ast)
+                                 // FIXME Error for MIR (needs support for union)
         }
         {
             let rma = &mut u.a;
-            u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+            u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
+                     //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed (Ast)
+                     // FIXME Error for MIR (needs support for union)
         }
     }
 }
diff --git a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
index fddb9838c44..b5916584930 100644
--- a/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 #![feature(slice_patterns)]
 
 fn main() {
@@ -17,7 +20,9 @@ fn main() {
         _ => unreachable!()
     };
     println!("t[0]: {}", t[0]);
-    a[2] = 0; //~ ERROR cannot assign to `a[..]` because it is borrowed
+    a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed
+              //[mir]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast)
+              // FIXME Error for MIR (error missed)
     println!("t[0]: {}", t[0]);
     t[0];
 }
diff --git a/src/test/compile-fail/cdylib-deps-must-be-static.rs b/src/test/compile-fail/cdylib-deps-must-be-static.rs
index 853507cbc6d..bf7189c21fb 100644
--- a/src/test/compile-fail/cdylib-deps-must-be-static.rs
+++ b/src/test/compile-fail/cdylib-deps-must-be-static.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: dependency `cdylib_dep` not found in rlib format
+// error-pattern: crate `cdylib_dep` required to be available in rlib format, but was not found
 // aux-build:cdylib-dep.rs
 // ignore-musl
 // ignore-emscripten
diff --git a/src/test/compile-fail/coerce-overloaded-autoderef.rs b/src/test/compile-fail/coerce-overloaded-autoderef.rs
index 14fbc34c43b..43b771ce5db 100644
--- a/src/test/compile-fail/coerce-overloaded-autoderef.rs
+++ b/src/test/compile-fail/coerce-overloaded-autoderef.rs
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 fn borrow_mut<T>(x: &mut T) -> &mut T { x }
 fn borrow<T>(x: &T) -> &T { x }
 
@@ -17,24 +20,32 @@ fn borrow2<T>(_: &mut T, _: &T) {}
 fn double_mut_borrow<T>(x: &mut Box<T>) {
     let y = borrow_mut(x);
     let z = borrow_mut(x);
-    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time (Ast)
+    //[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
 }
 
 fn double_imm_borrow(x: &mut Box<i32>) {
     let y = borrow(x);
     let z = borrow(x);
     **x += 1;
-    //~^ ERROR cannot assign to `**x` because it is borrowed
+    //[ast]~^ ERROR cannot assign to `**x` because it is borrowed
+    //[mir]~^^ ERROR cannot assign to `**x` because it is borrowed (Ast)
+    //[mir]~| ERROR cannot assign to `(*(*x))` because it is borrowed (Mir)
 }
 
 fn double_mut_borrow2<T>(x: &mut Box<T>) {
     borrow_mut2(x, x);
-    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time (Ast)
+    //[mir]~| ERROR cannot borrow `(*x)` as mutable more than once at a time (Mir)
 }
 
 fn double_borrow2<T>(x: &mut Box<T>) {
     borrow2(x, x);
-    //~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable
+    //[ast]~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable
+    //[mir]~^^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable (Ast)
+    //[mir]~| ERROR cannot borrow `(*x)` as immutable because it is also borrowed as mutable (Mir)
 }
 
 pub fn main() {}
diff --git a/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs b/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs
new file mode 100644
index 00000000000..1fb139bf07f
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-dotdoteq_in_patterns.rs
@@ -0,0 +1,16 @@
+// 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.
+
+pub fn main() {
+    match 22 {
+        0 ..= 3 => {} //~ ERROR `..=` syntax in patterns is experimental
+        _ => {}
+    }
+}
diff --git a/src/rustc/libc_shim/build.rs b/src/test/compile-fail/feature-gate-underscore-lifetimes.rs
index 546f60482e7..9da50c5c877 100644
--- a/src/rustc/libc_shim/build.rs
+++ b/src/test/compile-fail/feature-gate-underscore-lifetimes.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(warnings)]
+struct Foo<'a>(&'a u8);
 
-// See comments in Cargo.toml for why this exists
+fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable
+    Foo(x)
+}
 
 fn main() {
-    println!("cargo:rustc-cfg=stdbuild");
-    println!("cargo:rerun-if-changed=build.rs");
+    let x = 5;
+    let _ = foo(&x);
 }
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs
index be82d0a5f6d..2dbc6cb140d 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs
+++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs
@@ -8,23 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// `#![derive]` is interpreted (and raises errors) when it occurs at
-// contexts other than ADT definitions. This test checks cases where
-// the derive-macro does not exist.
+// This test checks cases where the derive-macro does not exist.
 
-#![derive(x3300)]
-//~^ ERROR cannot find derive macro `x3300` in this scope
-
-#[derive(x3300)]
-//~^ ERROR cannot find derive macro `x3300` in this scope
 mod derive {
-    mod inner { #![derive(x3300)] }
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    fn derive() { }
-
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
     union U { f: i32 }
@@ -36,12 +22,4 @@ mod derive {
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
     struct S;
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    type T = S;
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    impl S { }
 }
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs
index 41c3d0ef561..e5293ebb94d 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs
+++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// `#![derive]` is interpreted (and raises errors) when it occurs at
-// contexts other than ADT definitions. This test checks cases where
-// the derive-macro exists.
+// `#![derive]` raises errors when it occurs at contexts other than ADT
+// definitions.
 
 #![derive(Debug)]
 //~^ ERROR `derive` may only be applied to structs, enums and unions
diff --git a/src/test/compile-fail/hrtb-identity-fn-borrows.rs b/src/test/compile-fail/hrtb-identity-fn-borrows.rs
index 17939cf9fe0..b6216ce0589 100644
--- a/src/test/compile-fail/hrtb-identity-fn-borrows.rs
+++ b/src/test/compile-fail/hrtb-identity-fn-borrows.rs
@@ -11,6 +11,9 @@
 // Test that the `'a` in the where clause correctly links the region
 // of the output to the region of the input.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 trait FnLike<A,R> {
     fn call(&self, arg: A) -> R;
 }
@@ -21,7 +24,9 @@ fn call_repeatedly<F>(f: F)
     // Result is stored: cannot re-assign `x`
     let mut x = 3;
     let y = f.call(&x);
-    x = 5; //~ ERROR cannot assign
+    x = 5; //[ast]~ ERROR cannot assign
+           //[mir]~^ ERROR cannot assign to `x` because it is borrowed (Ast)
+           //[mir]~| ERROR cannot assign to `x` because it is borrowed (Mir)
 
     // Result is not stored: can re-assign `x`
     let mut x = 3;
diff --git a/src/test/compile-fail/impossible_range.rs b/src/test/compile-fail/impossible_range.rs
index 94e048fed65..e4465e9f6b6 100644
--- a/src/test/compile-fail/impossible_range.rs
+++ b/src/test/compile-fail/impossible_range.rs
@@ -18,12 +18,12 @@ pub fn main() {
     ..1;
     0..1;
 
-    ...; //~ERROR inclusive range with no end
+    ..=; //~ERROR inclusive range with no end
          //~^HELP bounded at the end
-    0...; //~ERROR inclusive range with no end
+    0..=; //~ERROR inclusive range with no end
           //~^HELP bounded at the end
-    ...1;
-    0...1;
+    ..=1;
+    0..=1;
 }
 
 
diff --git a/src/test/compile-fail/issue-43023.rs b/src/test/compile-fail/issue-43023.rs
new file mode 100644
index 00000000000..6a5f7a1136a
--- /dev/null
+++ b/src/test/compile-fail/issue-43023.rs
@@ -0,0 +1,28 @@
+// 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 S;
+
+impl S {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    fn f() {
+        file!();
+    }
+}
+
+trait Tr1 {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    fn f();
+}
+
+trait Tr2 {
+    #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions
+    type F;
+}
diff --git a/src/test/compile-fail/issue-43733.rs b/src/test/compile-fail/issue-43733.rs
index f10531e407d..90ccc589b4e 100644
--- a/src/test/compile-fail/issue-43733.rs
+++ b/src/test/compile-fail/issue-43733.rs
@@ -9,11 +9,13 @@
 // except according to those terms.
 
 #![feature(const_fn)]
+#![feature(thread_local)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 type Foo = std::cell::RefCell<String>;
 
 #[cfg(target_thread_local)]
+#[thread_local]
 static __KEY: std::thread::__FastLocalKeyInner<Foo> =
     std::thread::__FastLocalKeyInner::new();
 
@@ -25,7 +27,7 @@ fn __getit() -> std::option::Option<
     &'static std::cell::UnsafeCell<
         std::option::Option<Foo>>>
 {
-    __KEY.get() //~ ERROR  invocation of unsafe method requires unsafe
+    __KEY.get() //~ ERROR call to unsafe function requires unsafe
 }
 
 static FOO: std::thread::LocalKey<Foo> =
diff --git a/src/test/compile-fail/lifetime-underscore.rs b/src/test/compile-fail/label-underscore.rs
index 5b518a4931d..30411bf8789 100644
--- a/src/test/compile-fail/lifetime-underscore.rs
+++ b/src/test/compile-fail/label-underscore.rs
@@ -8,12 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn _f<'_>() //~ ERROR invalid lifetime name `'_`
-    -> &'_ u8 //~ ERROR invalid lifetime name `'_`
-{
-    panic!();
-}
-
 fn main() {
     '_: loop { //~ ERROR invalid label name `'_`
         break '_ //~ ERROR invalid label name `'_`
diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs
index 9bc2c021904..de455afbd66 100644
--- a/src/test/compile-fail/lint-stability-deprecated.rs
+++ b/src/test/compile-fail/lint-stability-deprecated.rs
@@ -107,6 +107,7 @@ mod cross_crate {
         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
         struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
         //~^ WARN use of deprecated item
+        //~| WARN use of deprecated item
 
         let _ = DeprecatedStruct { //~ WARN use of deprecated item
             i: 0 //~ WARN use of deprecated item
diff --git a/src/test/compile-fail/mut-pattern-internal-mutability.rs b/src/test/compile-fail/mut-pattern-internal-mutability.rs
index b0d618328dc..3a84bd6565e 100644
--- a/src/test/compile-fail/mut-pattern-internal-mutability.rs
+++ b/src/test/compile-fail/mut-pattern-internal-mutability.rs
@@ -8,11 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 fn main() {
     let foo = &mut 1;
 
     let &mut x = foo;
-    x += 1; //~ ERROR re-assignment of immutable variable
+    x += 1; //[ast]~ ERROR re-assignment of immutable variable
+            //[mir]~^ ERROR re-assignment of immutable variable `x` (Ast)
+            //[mir]~| ERROR re-assignment of immutable variable `x` (Mir)
 
     // explicitly mut-ify internals
     let &mut mut x = foo;
@@ -20,5 +25,7 @@ fn main() {
 
     // check borrowing is detected successfully
     let &mut ref x = foo;
-    *foo += 1; //~ ERROR cannot assign to `*foo` because it is borrowed
+    *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
+               //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed (Ast)
+               //[mir]~| ERROR cannot assign to `(*foo)` because it is borrowed (Mir)
 }
diff --git a/src/test/compile-fail/object-lifetime-default-mybox.rs b/src/test/compile-fail/object-lifetime-default-mybox.rs
index 014b0c1e80e..54657e76e97 100644
--- a/src/test/compile-fail/object-lifetime-default-mybox.rs
+++ b/src/test/compile-fail/object-lifetime-default-mybox.rs
@@ -34,7 +34,7 @@ fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
                 b: &'b MyBox<SomeTrait>)
                 -> &'b MyBox<SomeTrait>
 {
-    a //~ ERROR E0312
+    a //~ ERROR lifetime mismatch
 }
 
 fn load2<'a>(ss: &MyBox<SomeTrait+'a>) -> MyBox<SomeTrait+'a> {
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index 4d41f8ba47d..973d467b112 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -103,10 +103,11 @@ mod adjust {
 
 fn main() {
     let _: m::Alias; //~ ERROR type `m::Priv` is private
-    let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; // FIXME
+                     //~^ ERROR type `m::Priv` is private
+    let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; //~ ERROR type `m::Priv` is private
     m::Alias {}; //~ ERROR type `m::Priv` is private
     m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private
-    m::Pub { 0: loop {} }; // FIXME
+    m::Pub { 0: loop {} }; // OK, `m::Pub` is in value context, so it means Pub<_>, not Pub<Priv>
     m::Pub::static_method; //~ ERROR type `m::Priv` is private
     m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
     m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private
diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs
index a5581664f74..eb8c40a7dd5 100644
--- a/src/test/compile-fail/private-type-in-interface.rs
+++ b/src/test/compile-fail/private-type-in-interface.rs
@@ -31,7 +31,6 @@ fn f_ext(_: ext::Alias) {} //~ ERROR type `ext::Priv` is private
 trait Tr1 {}
 impl m::Alias {} //~ ERROR type `m::Priv` is private
 impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
-                           //~^ ERROR type `ext::Priv` is private
 type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private
 
 trait Tr2<T> {}
diff --git a/src/test/compile-fail/range_inclusive_gate.rs b/src/test/compile-fail/range_inclusive_gate.rs
index 1d1153e951b..69b9a4c67ad 100644
--- a/src/test/compile-fail/range_inclusive_gate.rs
+++ b/src/test/compile-fail/range_inclusive_gate.rs
@@ -14,7 +14,7 @@
 // #![feature(inclusive_range)]
 
 pub fn main() {
-    let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ... { use std::intrinsics; 2 };
+    let _: std::ops::RangeInclusive<_> = { use std::intrinsics; 1 } ..= { use std::intrinsics; 2 };
     //~^ ERROR use of unstable library feature 'inclusive_range'
     //~| ERROR core_intrinsics
     //~| ERROR core_intrinsics
diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs
index ae9ceb600d4..91f5f048bc1 100644
--- a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs
+++ b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs
@@ -8,13 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
 fn main() {
     let a0 = 0;
     let f = 1;
     let mut a1 = &a0;
     match (&a1,) {
         (&ref b0,) => {
-            a1 = &f; //~ ERROR cannot assign
+            a1 = &f; //[ast]~ ERROR cannot assign
+                     //[mir]~^ ERROR cannot assign to `a1` because it is borrowed (Ast)
+                     //[mir]~| ERROR cannot assign to `a1` because it is borrowed (Mir)
         }
     }
 }
diff --git a/src/test/compile-fail/rmeta_lib.rs b/src/test/compile-fail/rmeta_lib.rs
index 3b7d1f3cc90..a61ff05e8c8 100644
--- a/src/test/compile-fail/rmeta_lib.rs
+++ b/src/test/compile-fail/rmeta_lib.rs
@@ -10,7 +10,7 @@
 
 // aux-build:rmeta_meta.rs
 // no-prefer-dynamic
-// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available
+// error-pattern: crate `rmeta_meta` required to be available in rlib format, but was not found
 
 // Check that building a non-metadata crate fails if a dependent crate is
 // metadata-only.
diff --git a/src/test/compile-fail/synthetic-param.rs b/src/test/compile-fail/synthetic-param.rs
new file mode 100644
index 00000000000..a9762e383fe
--- /dev/null
+++ b/src/test/compile-fail/synthetic-param.rs
@@ -0,0 +1,38 @@
+// 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(generic_param_attrs, rustc_attrs)]
+
+fn func<#[rustc_synthetic] T>(_: T) {}
+
+struct Foo;
+
+impl Foo {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+struct Bar<S> {
+    t: S
+}
+
+impl<S> Bar<S> {
+    pub fn func<#[rustc_synthetic] T>(_: T) {}
+}
+
+fn main() {
+    func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    func(42); // Ok
+
+    Foo::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Foo::func(42); // Ok
+
+    Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit type parameters
+    Bar::<i8>::func(42); // Ok
+}
diff --git a/src/test/compile-fail/type-path-err-node-types.rs b/src/test/compile-fail/type-path-err-node-types.rs
new file mode 100644
index 00000000000..8f26777b441
--- /dev/null
+++ b/src/test/compile-fail/type-path-err-node-types.rs
@@ -0,0 +1,17 @@
+// 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.
+
+// Type arguments of unresolved types should have their types recorded
+
+fn main() {
+    let _: Nonexistent<u8, Assoc = u16>; //~ ERROR cannot find type `Nonexistent` in this scope
+
+    let _ = |a, b: _| -> _ { 0 };
+}
diff --git a/src/test/compile-fail/underscore-lifetime-binders.rs b/src/test/compile-fail/underscore-lifetime-binders.rs
new file mode 100644
index 00000000000..99b6e036f33
--- /dev/null
+++ b/src/test/compile-fail/underscore-lifetime-binders.rs
@@ -0,0 +1,39 @@
+// 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(underscore_lifetimes)]
+
+struct Foo<'a>(&'a u8);
+struct Baz<'a>(&'_ &'a u8); //~ ERROR missing lifetime specifier
+
+impl Foo<'_> { //~ ERROR missing lifetime specifier
+    fn x() {}
+}
+
+fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
+(_: Foo<'_>) {}
+
+trait Meh<'a> {}
+impl<'a> Meh<'a> for u8 {}
+
+fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
+//~^ ERROR missing lifetime specifier
+//~^^ ERROR missing lifetime specifier
+{
+  Box::new(5u8)
+}
+
+fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier
+
+fn main() {
+    let x = 5;
+    foo(Foo(&x));
+    let _ = meh();
+}
diff --git a/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs b/src/test/compile-fail/underscore-lifetime-elison-mismatch.rs
new file mode 100644
index 00000000000..a1c4e4a1fd9
--- /dev/null
+++ b/src/test/compile-fail/underscore-lifetime-elison-mismatch.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.
+
+#![feature(underscore_lifetimes)]
+
+fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
diff --git a/src/test/compile-fail/union/union-unsafe.rs b/src/test/compile-fail/union/union-unsafe.rs
index 2e018e696a4..e57d65dcb89 100644
--- a/src/test/compile-fail/union/union-unsafe.rs
+++ b/src/test/compile-fail/union/union-unsafe.rs
@@ -42,8 +42,8 @@ fn main() {
     let mut u1 = U1 { a: 10 }; // OK
     let a = u1.a; //~ ERROR access to union field requires unsafe
     u1.a = 11; // OK
-    let U1 { a } = u1; //~ ERROR matching on union field requires unsafe
-    if let U1 { a: 12 } = u1 {} //~ ERROR matching on union field requires unsafe
+    let U1 { a } = u1; //~ ERROR access to union field requires unsafe
+    if let U1 { a: 12 } = u1 {} //~ ERROR access to union field requires unsafe
     // let U1 { .. } = u1; // OK
 
     let mut u2 = U2 { a: String::from("old") }; // OK
diff --git a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs
index cff10329b85..f30da250f6a 100644
--- a/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs
+++ b/src/test/compile-fail/unsafe-fn-assign-deref-ptr.rs
@@ -1,3 +1,4 @@
+
 // 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.
@@ -9,7 +10,7 @@
 // except according to those terms.
 
 
-fn f(p: *const u8) {
+fn f(p: *mut u8) {
     *p = 0; //~ ERROR dereference of raw pointer requires unsafe function or block
     return;
 }
diff --git a/src/test/compile-fail/unsafe-move-val-init.rs b/src/test/compile-fail/unsafe-move-val-init.rs
new file mode 100644
index 00000000000..84a8c84a0db
--- /dev/null
+++ b/src/test/compile-fail/unsafe-move-val-init.rs
@@ -0,0 +1,20 @@
+// 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(core_intrinsics)]
+
+use std::intrinsics;
+
+// `move_val_init` has an odd desugaring, check that it is still treated
+// as unsafe.
+fn main() {
+    intrinsics::move_val_init(1 as *mut u32, 1);
+    //~^ ERROR dereference of raw pointer requires unsafe function or block
+}
diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs
index 9e56d34636f..355983e9ca1 100644
--- a/src/test/incremental/callee_caller_cross_crate/b.rs
+++ b/src/test/incremental/callee_caller_cross_crate/b.rs
@@ -12,6 +12,8 @@
 // revisions:rpass1 rpass2
 // compile-flags:-Z query-dep-graph
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 
 extern crate a;
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..d58a9bacdb5 100644
--- a/src/test/incremental/change_private_fn_cc/struct_point.rs
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -15,6 +15,8 @@
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
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..3f665f5c820 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
@@ -15,6 +15,8 @@
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
 #![allow(dead_code)]
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
index b828cc9c70a..6d54cf53660 100644
--- a/src/test/incremental/dirty_clean.rs
+++ b/src/test/incremental/dirty_clean.rs
@@ -37,7 +37,7 @@ mod y {
 
     #[rustc_clean(label="TypeckTables", cfg="cfail2")]
     pub fn y() {
-        //[cfail2]~^ ERROR `TypeckTables(y::y)` not found in dep graph, but should be clean
+        //[cfail2]~^ ERROR `TypeckTables(y::y)` should be clean but is not
         x::x();
     }
 }
@@ -45,6 +45,6 @@ mod y {
 mod z {
     #[rustc_dirty(label="TypeckTables", cfg="cfail2")]
     pub fn z() {
-        //[cfail2]~^ ERROR `TypeckTables(z::z)` found in dep graph, but should be dirty
+        //[cfail2]~^ ERROR `TypeckTables(z::z)` should be dirty but is not
     }
 }
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index 0f734683b60..8f84266d5a4 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -143,7 +143,7 @@ enum EnumChangeValueCStyleVariant1 {
 #[cfg(not(cfail1))]
 #[rustc_dirty(label="Hir", cfg="cfail2")]
 #[rustc_clean(label="Hir", cfg="cfail3")]
-#[rustc_clean(label="HirBody", cfg="cfail2")]
+#[rustc_dirty(label="HirBody", cfg="cfail2")]
 #[rustc_clean(label="HirBody", cfg="cfail3")]
 #[rustc_metadata_dirty(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index bb31982d93f..a12624d0832 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -153,5 +153,5 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
-    &slice[3...7]
+    &slice[3..=7]
 }
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
index 9849e93d3ff..39065d9671a 100644
--- a/src/test/incremental/rlib_cross_crate/b.rs
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -18,6 +18,8 @@
 // no-prefer-dynamic
 // compile-flags: -Z query-dep-graph
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 
 extern crate a;
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index 36a26cf1755..760975b292f 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -27,7 +27,8 @@ mod x {
     }
 
     #[cfg(rpass2)]
-    #[rustc_dirty(label="TypeckTables", cfg="rpass2")]
+    #[rustc_dirty(label="HirBody", cfg="rpass2")]
+    #[rustc_dirty(label="MirOptimized", cfg="rpass2")]
     pub fn x() {
         println!("{}", "2");
     }
@@ -37,6 +38,7 @@ mod y {
     use x;
 
     #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
     pub fn y() {
         x::x();
     }
@@ -46,6 +48,7 @@ mod z {
     use y;
 
     #[rustc_clean(label="TypeckTables", cfg="rpass2")]
+    #[rustc_clean(label="MirOptimized", cfg="rpass2")]
     pub fn z() {
         y::y();
     }
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
index 9660f47da35..e5ec9784847 100644
--- a/src/test/incremental/struct_change_field_type_cross_crate/b.rs
+++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
@@ -12,6 +12,8 @@
 // revisions:rpass1 rpass2
 // compile-flags: -Z query-dep-graph
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 
 extern crate a;
diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs
index ee35a4d9b9c..63e1437f068 100644
--- a/src/test/incremental/type_alias_cross_crate/b.rs
+++ b/src/test/incremental/type_alias_cross_crate/b.rs
@@ -12,6 +12,8 @@
 // revisions:rpass1 rpass2 rpass3
 // compile-flags: -Z query-dep-graph
 
+// ignore-test -- ignored until red/green restores cross-crate tracking fidelity
+
 #![feature(rustc_attrs)]
 
 extern crate a;
diff --git a/src/test/parse-fail/pat-ranges-1.rs b/src/test/parse-fail/pat-ranges-1.rs
index e1cbb961b1b..857a3924aec 100644
--- a/src/test/parse-fail/pat-ranges-1.rs
+++ b/src/test/parse-fail/pat-ranges-1.rs
@@ -11,5 +11,5 @@
 // Parsing of range patterns
 
 fn main() {
-    let macropus!() ... 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `...`
+    let macropus!() ..= 11 = 12; //~ error: expected one of `:`, `;`, or `=`, found `..=`
 }
diff --git a/src/test/parse-fail/pat-ranges-2.rs b/src/test/parse-fail/pat-ranges-2.rs
index 04ad5ff083b..64c749333cf 100644
--- a/src/test/parse-fail/pat-ranges-2.rs
+++ b/src/test/parse-fail/pat-ranges-2.rs
@@ -11,5 +11,5 @@
 // Parsing of range patterns
 
 fn main() {
-    let 10 ... makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
+    let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!`
 }
diff --git a/src/test/parse-fail/pat-ranges-3.rs b/src/test/parse-fail/pat-ranges-3.rs
index 5f7aac71d29..1327a9fab36 100644
--- a/src/test/parse-fail/pat-ranges-3.rs
+++ b/src/test/parse-fail/pat-ranges-3.rs
@@ -11,5 +11,5 @@
 // Parsing of range patterns
 
 fn main() {
-    let 10 ... 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+`
+    let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, or `=`, found `+`
 }
diff --git a/src/test/parse-fail/pat-ranges-4.rs b/src/test/parse-fail/pat-ranges-4.rs
index 4bbf387d1c0..c159c770250 100644
--- a/src/test/parse-fail/pat-ranges-4.rs
+++ b/src/test/parse-fail/pat-ranges-4.rs
@@ -11,5 +11,6 @@
 // Parsing of range patterns
 
 fn main() {
-    let 10 - 3 ... 10 = 8; //~ error: expected one of `...`, `..`, `:`, `;`, or `=`, found `-`
+    let 10 - 3 ..= 10 = 8;
+    //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, or `=`, found `-`
 }
diff --git a/src/test/parse-fail/range_inclusive.rs b/src/test/parse-fail/range_inclusive.rs
index ce97372c668..cc32b9903b5 100644
--- a/src/test/parse-fail/range_inclusive.rs
+++ b/src/test/parse-fail/range_inclusive.rs
@@ -13,7 +13,7 @@
 #![feature(inclusive_range_syntax, inclusive_range)]
 
 pub fn main() {
-    for _ in 1... {} //~ERROR inclusive range with no end
+    for _ in 1..= {} //~ERROR inclusive range with no end
                      //~^HELP bounded at the end
 }
 
diff --git a/src/test/parse-fail/range_inclusive_gate.rs b/src/test/parse-fail/range_inclusive_gate.rs
index 30dc6fc5b20..de690c3fea3 100644
--- a/src/test/parse-fail/range_inclusive_gate.rs
+++ b/src/test/parse-fail/range_inclusive_gate.rs
@@ -15,21 +15,21 @@
 // #![feature(inclusive_range_syntax, inclusive_range)]
 
 macro_rules! m {
-    () => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental
+    () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental
 }
 
 #[cfg(nope)]
 fn f() {}
 #[cfg(not(nope))]
 fn f() {
-    for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
+    for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
 }
 
 #[cfg(nope)]
 macro_rules! n { () => {} }
 #[cfg(not(nope))]
 macro_rules! n {
-    () => { for _ in 1...10 {} } //~ ERROR inclusive range syntax is experimental
+    () => { for _ in 1..=10 {} } //~ ERROR inclusive range syntax is experimental
 }
 
 macro_rules! o {
@@ -38,7 +38,7 @@ macro_rules! o {
         fn g() {}
         #[cfg(not(nope))]
         fn g() {
-            for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
+            for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
         }
 
         g();
@@ -54,7 +54,7 @@ macro_rules! p {
         fn h() {}
         #[cfg(not(nope))]
         fn h() {
-            for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
+            for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
         }
 
         h();
@@ -62,8 +62,8 @@ macro_rules! p {
 }
 
 pub fn main() {
-    for _ in 1...10 {} //~ ERROR inclusive range syntax is experimental
-    for _ in ...10 {} //~ ERROR inclusive range syntax is experimental
+    for _ in 1..=10 {} //~ ERROR inclusive range syntax is experimental
+    for _ in ..=10 {} //~ ERROR inclusive range syntax is experimental
 
     f(); // not allowed in cfg'ed functions
 
diff --git a/src/test/run-make/codegen-options-parsing/Makefile b/src/test/run-make/codegen-options-parsing/Makefile
index dc46a8a04ef..755e211a349 100644
--- a/src/test/run-make/codegen-options-parsing/Makefile
+++ b/src/test/run-make/codegen-options-parsing/Makefile
@@ -1,26 +1,28 @@
 -include ../tools.mk
 
+LOG = $(TMPDIR)/log.txt
+
 all:
 	#Option taking a number
-	$(RUSTC) -C codegen-units dummy.rs 2>&1 | \
-		grep 'codegen option `codegen-units` requires a number'
-	$(RUSTC) -C codegen-units= dummy.rs 2>&1 | \
-		grep 'incorrect value `` for codegen option `codegen-units` - a number was expected'
-	$(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \
-		grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected'
+	$(RUSTC) -C codegen-units dummy.rs 2>&1 | tee $(LOG)
+	grep 'codegen option `codegen-units` requires a number' $(LOG)
+	$(RUSTC) -C codegen-units= dummy.rs 2>&1 | tee $(LOG)
+	grep 'incorrect value `` for codegen option `codegen-units` - a number was expected' $(LOG)
+	$(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | tee $(LOG)
+	grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected' $(LOG)
 	$(RUSTC) -C codegen-units=1 dummy.rs
 	#Option taking a string
-	$(RUSTC) -C extra-filename dummy.rs 2>&1 | \
-		grep 'codegen option `extra-filename` requires a string'
+	$(RUSTC) -C extra-filename dummy.rs 2>&1 | tee $(LOG)
+	grep 'codegen option `extra-filename` requires a string' $(LOG)
 	$(RUSTC) -C extra-filename= dummy.rs 2>&1
 	$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
 	#Option taking no argument
-	$(RUSTC) -C lto= dummy.rs 2>&1 | \
-		grep 'codegen option `lto` takes no value'
-	$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
-		grep 'codegen option `lto` takes no value'
-	$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
-		grep 'codegen option `lto` takes no value'
+	$(RUSTC) -C lto= dummy.rs 2>&1 | tee $(LOG)
+	grep 'codegen option `lto` takes no value' $(LOG)
+	$(RUSTC) -C lto=1 dummy.rs 2>&1 | tee $(LOG)
+	grep 'codegen option `lto` takes no value' $(LOG)
+	$(RUSTC) -C lto=foo dummy.rs 2>&1 | tee $(LOG)
+	grep 'codegen option `lto` takes no value' $(LOG)
 	$(RUSTC) -C lto dummy.rs
 
 	# Should not link dead code...
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
index 7a63871f19e..2ff4593a801 100644
--- a/src/test/run-make/llvm-phase/test.rs
+++ b/src/test/run-make/llvm-phase/test.rs
@@ -77,6 +77,7 @@ fn main() {
         .split(' ').map(|s| s.to_string()).collect();
     args.push("--out-dir".to_string());
     args.push(env::var("TMPDIR").unwrap());
+    args.push("-Ccodegen-units=1".to_string());
 
     let (result, _) = rustc_driver::run_compiler(
         &args, &mut JitCalls, Some(box JitLoader), None);
diff --git a/src/test/ui/mismatched_types/E0281.rs b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs
index abb66c99fab..5a28d756df5 100644
--- a/src/test/ui/mismatched_types/E0281.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/attr-cfg.rs
@@ -8,18 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo<F: Fn(usize)>(x: F) { }
+// aux-build:attr-cfg.rs
+// ignore-stage1
+// revisions: foo bar
 
+#![feature(proc_macro)]
+
+extern crate attr_cfg;
+use attr_cfg::attr_cfg;
+
+#[attr_cfg]
+fn outer() -> u8 {
+    #[cfg(foo)]
+    fn inner() -> u8 { 1 }
+
+    #[cfg(bar)]
+    fn inner() -> u8 { 2 }
+
+    inner()
+}
+
+#[cfg(foo)]
+fn main() {
+    assert_eq!(outer(), 1);
+}
+
+#[cfg(bar)]
 fn main() {
-    foo(|y: String| { });
-    //~^ ERROR E0281
-    //~| ERROR E0281
-    //~| NOTE implements
-    //~| NOTE implements
-    //~| NOTE requires
-    //~| NOTE requires
-    //~| NOTE expected usize, found struct `std::string::String`
-    //~| NOTE expected usize, found struct `std::string::String`
-    //~| NOTE required by `foo`
-    //~| NOTE required by `foo`
+    assert_eq!(outer(), 2);
 }
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs
new file mode 100644
index 00000000000..9145c46cfc7
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-cfg.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// no-prefer-dynamic
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream {
+    let input_str = input.to_string();
+
+    assert_eq!(input_str, "fn outer() -> u8 {
+    #[cfg(foo)]
+    fn inner() -> u8 { 1 }
+    #[cfg(bar)]
+    fn inner() -> u8 { 2 }
+    inner()
+}");
+
+    input
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs
new file mode 100644
index 00000000000..787a4a470e2
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-attr-cfg.rs
@@ -0,0 +1,23 @@
+// 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.
+
+// no-prefer-dynamic
+#![feature(proc_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo, attributes(foo))]
+pub fn derive(input: TokenStream) -> TokenStream {
+    assert!(!input.to_string().contains("#[cfg(any())]"));
+    "".parse().unwrap()
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs
new file mode 100644
index 00000000000..b94c45248da
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/derive-attr-cfg.rs
@@ -0,0 +1,27 @@
+// 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.
+
+// aux-build:derive-attr-cfg.rs
+// ignore-stage1
+
+#![feature(proc_macro)]
+
+extern crate derive_attr_cfg;
+use derive_attr_cfg::Foo;
+
+#[derive(Foo)]
+#[foo]
+struct S {
+    #[cfg(any())]
+    x: i32
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass-valgrind/issue-44800.rs b/src/test/run-pass-valgrind/issue-44800.rs
new file mode 100644
index 00000000000..cfde6f32f66
--- /dev/null
+++ b/src/test/run-pass-valgrind/issue-44800.rs
@@ -0,0 +1,25 @@
+// 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(global_allocator, alloc_system, allocator_api)]
+extern crate alloc_system;
+
+use std::collections::VecDeque;
+use alloc_system::System;
+
+#[global_allocator]
+static ALLOCATOR: System = System;
+
+fn main() {
+    let mut deque = VecDeque::with_capacity(32);
+    deque.push_front(0);
+    deque.reserve(31);
+    deque.push_back(0);
+}
diff --git a/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs b/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs
index b36afcf87b3..0bfc4d2264c 100644
--- a/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs
+++ b/src/test/run-pass/for-loop-unconstrained-element-type-i32-fallback.rs
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 // Test that the type of `sum` falls back to `i32` here,
-// and that the for loop desugaring doesn't inferfere with
+// and that the for loop desugaring doesn't interfere with
 // that.
 
 fn main() {
     let mut sum = 0;
     for i in Vec::new() {
-        sum += i;
+        sum += &i;
     }
 }
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index cef2f879f9c..08e9990511f 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -13,6 +13,7 @@
 #![allow(unused_features)]
 #![feature(box_syntax)]
 
+use std::cell::RefCell;
 use std::fmt::{self, Write};
 use std::usize;
 
@@ -240,6 +241,8 @@ pub fn main() {
     // test that trailing commas are acceptable
     format!("{}", "test",);
     format!("{foo}", foo="test",);
+
+    test_refcell();
 }
 
 // Basic test to make sure that we can invoke the `write!` macro with an
@@ -319,3 +322,12 @@ fn test_once() {
     assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a=foo()),
                "1 1 1 2 2 2".to_string());
 }
+
+fn test_refcell() {
+    let refcell = RefCell::new(5);
+    assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }");
+    let borrow = refcell.borrow_mut();
+    assert_eq!(format!("{:?}", refcell), "RefCell { value: <borrowed> }");
+    drop(borrow);
+    assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }");
+}
diff --git a/src/test/run-pass/inc-range-pat.rs b/src/test/run-pass/inc-range-pat.rs
new file mode 100644
index 00000000000..5faf36eddaf
--- /dev/null
+++ b/src/test/run-pass/inc-range-pat.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.
+
+// Test old and new syntax for inclusive range patterns.
+#![feature(dotdoteq_in_patterns)]
+
+
+fn main() {
+    assert!(match 42 { 0 ... 100 => true, _ => false });
+    assert!(match 42 { 0 ..= 100 => true, _ => false });
+
+    assert!(match 'x' { 'a' ... 'z' => true, _ => false });
+    assert!(match 'x' { 'a' ..= 'z' => true, _ => false });
+}
+
diff --git a/src/test/run-pass/issue-44730.rs b/src/test/run-pass/issue-44730.rs
new file mode 100644
index 00000000000..6e8aba01255
--- /dev/null
+++ b/src/test/run-pass/issue-44730.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.
+
+//! dox
+
+#![deny(missing_docs)]
+
+macro_rules! doc {
+    ($e:expr) => (
+        #[doc = $e]
+        pub struct Foo;
+    )
+}
+
+doc!("a");
+
+fn main() {}
diff --git a/src/test/run-pass/num-wrapping.rs b/src/test/run-pass/num-wrapping.rs
index 143759e2715..20c7f27336e 100644
--- a/src/test/run-pass/num-wrapping.rs
+++ b/src/test/run-pass/num-wrapping.rs
@@ -173,6 +173,15 @@ fn test_op_assigns() {
                 tmp.$op(Wrapping($rhs));
                 assert_eq!(black_box(tmp), Wrapping($ans));
             }
+
+            // also test that a &Wrapping<T> right-hand side is possible
+            {
+                let mut tmp = Wrapping($initial);
+                tmp = black_box(tmp);
+                tmp.$op(&Wrapping($rhs));
+                assert_eq!(black_box(tmp), Wrapping($ans));
+            }
+
             // FIXME(30524): Uncomment this test
             /*
             {
diff --git a/src/test/run-pass/op-assign-builtins-by-ref.rs b/src/test/run-pass/op-assign-builtins-by-ref.rs
new file mode 100644
index 00000000000..230d44ba647
--- /dev/null
+++ b/src/test/run-pass/op-assign-builtins-by-ref.rs
@@ -0,0 +1,84 @@
+// 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.
+
+fn main() {
+    // test compound assignment operators with ref as right-hand side,
+    // for each operator, with various types as operands.
+
+    // test AddAssign
+    {
+        let mut x = 3i8;
+        x += &2i8;
+        assert_eq!(x, 5i8);
+    }
+
+    // test SubAssign
+    {
+        let mut x = 7i16;
+        x -= &4;
+        assert_eq!(x, 3i16);
+    }
+
+    // test MulAssign
+    {
+        let mut x = 3f32;
+        x *= &3f32;
+        assert_eq!(x, 9f32);
+    }
+
+    // test DivAssign
+    {
+        let mut x = 6f64;
+        x /= &2f64;
+        assert_eq!(x, 3f64);
+    }
+
+    // test RemAssign
+    {
+        let mut x = 7i64;
+        x %= &4i64;
+        assert_eq!(x, 3i64);
+    }
+
+    // test BitOrAssign
+    {
+        let mut x = 0b1010u8;
+        x |= &0b1100u8;
+        assert_eq!(x, 0b1110u8);
+    }
+
+    // test BitAndAssign
+    {
+        let mut x = 0b1010u16;
+        x &= &0b1100u16;
+        assert_eq!(x, 0b1000u16);
+    }
+
+    // test BitXorAssign
+    {
+        let mut x = 0b1010u32;
+        x ^= &0b1100u32;
+        assert_eq!(x, 0b0110u32);
+    }
+
+    // test ShlAssign
+    {
+        let mut x = 0b1010u64;
+        x <<= &2u32;
+        assert_eq!(x, 0b101000u64);
+    }
+
+    // test ShrAssign
+    {
+        let mut x = 0b1010u64;
+        x >>= &2i16;
+        assert_eq!(x, 0b10u64);
+    }
+}
diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs
index f6119e70999..71e11804052 100644
--- a/src/test/run-pass/range_inclusive.rs
+++ b/src/test/run-pass/range_inclusive.rs
@@ -17,18 +17,18 @@ use std::ops::{RangeInclusive, RangeToInclusive};
 fn foo() -> isize { 42 }
 
 // Test that range syntax works in return statements
-fn return_range_to() -> RangeToInclusive<i32> { return ...1; }
+fn return_range_to() -> RangeToInclusive<i32> { return ..=1; }
 
 pub fn main() {
     let mut count = 0;
-    for i in 0_usize...10 {
+    for i in 0_usize..=10 {
         assert!(i >= 0 && i <= 10);
         count += i;
     }
     assert_eq!(count, 55);
 
     let mut count = 0;
-    let mut range = 0_usize...10;
+    let mut range = 0_usize..=10;
     for i in range {
         assert!(i >= 0 && i <= 10);
         count += i;
@@ -36,53 +36,53 @@ pub fn main() {
     assert_eq!(count, 55);
 
     let mut count = 0;
-    for i in (0_usize...10).step_by(2) {
+    for i in (0_usize..=10).step_by(2) {
         assert!(i >= 0 && i <= 10 && i % 2 == 0);
         count += i;
     }
     assert_eq!(count, 30);
 
-    let _ = 0_usize...4+4-3;
-    let _ = 0...foo();
+    let _ = 0_usize..=4+4-3;
+    let _ = 0..=foo();
 
-    let _ = { &42...&100 }; // references to literals are OK
-    let _ = ...42_usize;
+    let _ = { &42..=&100 }; // references to literals are OK
+    let _ = ..=42_usize;
 
     // Test we can use two different types with a common supertype.
     let x = &42;
     {
         let y = 42;
-        let _ = x...&y;
+        let _ = x..=&y;
     }
 
     // test collection indexing
-    let vec = (0...10).collect::<Vec<_>>();
+    let vec = (0..=10).collect::<Vec<_>>();
     let slice: &[_] = &*vec;
     let string = String::from("hello world");
     let stir = "hello world";
 
-    assert_eq!(&vec[3...6], &[3, 4, 5, 6]);
-    assert_eq!(&vec[ ...6], &[0, 1, 2, 3, 4, 5, 6]);
+    assert_eq!(&vec[3..=6], &[3, 4, 5, 6]);
+    assert_eq!(&vec[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
 
-    assert_eq!(&slice[3...6], &[3, 4, 5, 6]);
-    assert_eq!(&slice[ ...6], &[0, 1, 2, 3, 4, 5, 6]);
+    assert_eq!(&slice[3..=6], &[3, 4, 5, 6]);
+    assert_eq!(&slice[ ..=6], &[0, 1, 2, 3, 4, 5, 6]);
 
-    assert_eq!(&string[3...6], "lo w");
-    assert_eq!(&string[ ...6], "hello w");
+    assert_eq!(&string[3..=6], "lo w");
+    assert_eq!(&string[ ..=6], "hello w");
 
-    assert_eq!(&stir[3...6], "lo w");
-    assert_eq!(&stir[ ...6], "hello w");
+    assert_eq!(&stir[3..=6], "lo w");
+    assert_eq!(&stir[ ..=6], "hello w");
 
     // test the size hints and emptying
-    let mut long = 0...255u8;
-    let mut short = 42...42u8;
+    let mut long = 0..=255u8;
+    let mut short = 42..=42u8;
     assert_eq!(long.size_hint(), (256, Some(256)));
     assert_eq!(short.size_hint(), (1, Some(1)));
     long.next();
     short.next();
     assert_eq!(long.size_hint(), (255, Some(255)));
     assert_eq!(short.size_hint(), (0, Some(0)));
-    assert_eq!(short, 1...0);
+    assert_eq!(short, 1..=0);
 
     assert_eq!(long.len(), 255);
     assert_eq!(short.len(), 0);
@@ -94,31 +94,31 @@ pub fn main() {
     assert_eq!(long.next(), Some(1));
     assert_eq!(long.next(), Some(2));
     assert_eq!(long.next_back(), Some(252));
-    for i in 3...251 {
+    for i in 3..=251 {
         assert_eq!(long.next(), Some(i));
     }
-    assert_eq!(long, 1...0);
+    assert_eq!(long, 1..=0);
 
     // check underflow
-    let mut narrow = 1...0;
+    let mut narrow = 1..=0;
     assert_eq!(narrow.next_back(), None);
-    assert_eq!(narrow, 1...0);
-    let mut zero = 0u8...0;
+    assert_eq!(narrow, 1..=0);
+    let mut zero = 0u8..=0;
     assert_eq!(zero.next_back(), Some(0));
     assert_eq!(zero.next_back(), None);
-    assert_eq!(zero, 1...0);
-    let mut high = 255u8...255;
+    assert_eq!(zero, 1..=0);
+    let mut high = 255u8..=255;
     assert_eq!(high.next_back(), Some(255));
     assert_eq!(high.next_back(), None);
-    assert_eq!(high, 1...0);
+    assert_eq!(high, 1..=0);
 
     // what happens if you have a nonsense range?
-    let mut nonsense = 10...5;
+    let mut nonsense = 10..=5;
     assert_eq!(nonsense.next(), None);
-    assert_eq!(nonsense, 10...5);
+    assert_eq!(nonsense, 10..=5);
 
     // output
-    assert_eq!(format!("{:?}", 0...10), "0...10");
-    assert_eq!(format!("{:?}", ...10), "...10");
-    assert_eq!(format!("{:?}", long), "1...0");
+    assert_eq!(format!("{:?}", 0..=10), "0..=10");
+    assert_eq!(format!("{:?}", ..=10), "..=10");
+    assert_eq!(format!("{:?}", long), "1..=0");
 }
diff --git a/src/test/run-pass/range_inclusive_gate.rs b/src/test/run-pass/range_inclusive_gate.rs
index 5e0ec19d6b3..570087aedbb 100644
--- a/src/test/run-pass/range_inclusive_gate.rs
+++ b/src/test/run-pass/range_inclusive_gate.rs
@@ -14,7 +14,7 @@
 
 fn main() {
     let mut count = 0;
-    for i in 0_usize...10 {
+    for i in 0_usize..=10 {
         assert!(i >= 0 && i <= 10);
         count += i;
     }
diff --git a/src/test/run-pass/underscore-lifetimes.rs b/src/test/run-pass/underscore-lifetimes.rs
new file mode 100644
index 00000000000..ed0369353bc
--- /dev/null
+++ b/src/test/run-pass/underscore-lifetimes.rs
@@ -0,0 +1,47 @@
+// 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(underscore_lifetimes)]
+
+struct Foo<'a>(&'a u8);
+
+fn foo(x: &u8) -> Foo<'_> {
+    Foo(x)
+}
+
+fn foo2(x: &'_ u8) -> Foo<'_> {
+    Foo(x)
+}
+
+fn foo3(x: &'_ u8) -> Foo {
+    Foo(x)
+}
+
+fn foo4(_: Foo<'_>) {}
+
+struct Foo2<'a, 'b> {
+    a: &'a u8,
+    b: &'b u8,
+}
+fn foo5<'b>(foo: Foo2<'_, 'b>) -> &'b u8 {
+    foo.b
+}
+
+fn main() {
+    let x = &5;
+    let _ = foo(x);
+    let _ = foo2(x);
+    let _ = foo3(x);
+    foo4(Foo(x));
+    let _ = foo5(Foo2 {
+        a: x,
+        b: &6,
+    });
+}
diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs
new file mode 100644
index 00000000000..5998734e4a2
--- /dev/null
+++ b/src/test/rustdoc/pub-method.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.
+
+// ignore-tidy-linelength
+// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
+
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html
+// @has - '//*[@class="rust fn"]' 'pub fn bar() -> '
+/// foo
+pub fn bar() -> usize {
+    2
+}
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="method"]' 'pub fn new()'
+// @has - '//*[@class="method"]' 'fn not_pub()'
+pub struct Foo(usize);
+
+impl Foo {
+    pub fn new() -> Foo { Foo(0) }
+    fn not_pub() {}
+}
diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
index 7c9c4e99039..0cc3a5b6bf3 100644
--- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
+++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr
@@ -2,7 +2,7 @@ warning: function is never used: `lintme`
   --> $DIR/lint-plugin-cmdline-allow.rs:20:1
    |
 20 | fn lintme() { }
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/lint-plugin-cmdline-allow.rs:17:9
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index 4b1f8b032b7..e3f0df6fb5f 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -3,6 +3,8 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
    |
 13 |         || self.b()
    |                 ^
+   |
+   = help: did you mean `a`?
 
 error[E0308]: mismatched types
   --> $DIR/issue-3563.rs:13:9
diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs
new file mode 100644
index 00000000000..16d8226bfec
--- /dev/null
+++ b/src/test/ui/deref-suggestion.rs
@@ -0,0 +1,34 @@
+// 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! borrow {
+    ($x:expr) => { &$x }
+}
+
+fn foo(_: String) {}
+
+fn foo2(s: &String) {
+    foo(s);
+}
+
+fn foo3(_: u32) {}
+fn foo4(u: &u32) {
+    foo3(u);
+}
+
+fn main() {
+    let s = String::new();
+    let r_s = &s;
+    foo2(r_s);
+    foo(&"aaa".to_owned());
+    foo(&mut "aaa".to_owned());
+    foo3(borrow!(0));
+    foo4(&0);
+}
diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr
new file mode 100644
index 00000000000..5ad9c19fa8c
--- /dev/null
+++ b/src/test/ui/deref-suggestion.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:18:9
+   |
+18 |     foo(s);
+   |         ^ expected struct `std::string::String`, found reference
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+   = help: here are some functions which might fulfill your needs:
+           - .escape_debug()
+           - .escape_default()
+           - .escape_unicode()
+           - .to_lowercase()
+           - .to_uppercase()
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:23:10
+   |
+23 |     foo3(u);
+   |          ^ expected u32, found &u32
+   |
+   = note: expected type `u32`
+              found type `&u32`
+   = help: try with `*u`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:30:9
+   |
+30 |     foo(&"aaa".to_owned());
+   |         ^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found reference
+   |
+   = note: expected type `std::string::String`
+              found type `&std::string::String`
+   = help: try with `"aaa".to_owned()`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:31:9
+   |
+31 |     foo(&mut "aaa".to_owned());
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found mutable reference
+   |
+   = note: expected type `std::string::String`
+              found type `&mut std::string::String`
+   = help: try with `"aaa".to_owned()`
+
+error[E0308]: mismatched types
+  --> $DIR/deref-suggestion.rs:12:20
+   |
+12 |     ($x:expr) => { &$x }
+   |                    ^^^ expected u32, found &{integer}
+...
+32 |     foo3(borrow!(0));
+   |          ---------- in this macro invocation
+   |
+   = note: expected type `u32`
+              found type `&{integer}`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
index 9e4f6c42179..cb9a1edf1dd 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
@@ -1,27 +1,13 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0623]: lifetime mismatch
   --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
    |
+19 |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |                   ----                 -------
+   |                   |
+   |                   this parameter and the return type are declared with different lifetimes...
+20 | 
 21 |         if x > y { x } else { y }
-   |                    ^
-   |
-note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5...
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
-   |
-19 | /     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
-20 | |
-21 | |         if x > y { x } else { y }
-22 | |
-23 | |     }
-   | |_____^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5
-  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
-   |
-19 | /     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
-20 | |
-21 | |         if x > y { x } else { y }
-22 | |
-23 | |     }
-   | |_____^
+   |                    ^ ...but data from `x` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
index e3fd0192053..8af6acc62c4 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
@@ -1,27 +1,13 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0623]: lifetime mismatch
   --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
    |
+16 |   fn foo<'a>(&self, x: &'a i32) -> &i32 {
+   |                        -------     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
+17 | 
 18 |     x
-   |     ^
-   |
-note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
-  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
-   |
-16 | /   fn foo<'a>(&self, x: &'a i32) -> &i32 {
-17 | |
-18 | |     x
-19 | |
-20 | |   }
-   | |___^
-note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3
-  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
-   |
-16 | /   fn foo<'a>(&self, x: &'a i32) -> &i32 {
-17 | |
-18 | |     x
-19 | |
-20 | |   }
-   | |___^
+   |     ^ ...but data from `x` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
index 8551f015db5..c09de0c33af 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
@@ -1,27 +1,13 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0623]: lifetime mismatch
   --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
    |
+16 |     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+   |                -----                 -------
+   |                |
+   |                this parameter and the return type are declared with different lifetimes...
+17 | 
 18 |         if true { x } else { self }
-   |                              ^^^^
-   |
-note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5...
-  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
-   |
-16 | /     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
-17 | |
-18 | |         if true { x } else { self }
-19 | |
-20 | |     }
-   | |_____^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5
-  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
-   |
-16 | /     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
-17 | |
-18 | |         if true { x } else { self }
-19 | |
-20 | |     }
-   | |_____^
+   |                              ^^^^ ...but data from `self` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
index 1b5ac7c7b57..73460277de4 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
@@ -4,7 +4,7 @@ error[E0623]: lifetime mismatch
 15 | fn foo(mut x: Ref) {
    |               ---
    |               |
-   |               this type was declared with multiple lifetimes...
+   |               this type is declared with multiple lifetimes...
 16 |     x.a = x.b;
    |           ^^^ ...but data with one lifetime flows into the other here
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr
index 689a1ac292b..fb524ae62c5 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-4.stderr
@@ -4,7 +4,7 @@ error[E0623]: lifetime mismatch
 15 | fn foo(mut x: Ref) {
    |               ---
    |               |
-   |               this type was declared with multiple lifetimes...
+   |               this type is declared with multiple lifetimes...
 16 |     x.a = x.b;
    |           ^^^ ...but data with one lifetime flows into the other here
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
index 890f9b311e7..1409b216133 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -1,23 +1,12 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
    |
+16 |   fn foo<'a>(&self, x: &i32) -> &i32 {
+   |                        ----     ----
+   |                        |
+   |                        this parameter and the return type are declared with different lifetimes...
 17 |     x
-   |     ^
-   |
-note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
-  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
-   |
-16 | /   fn foo<'a>(&self, x: &i32) -> &i32 {
-17 | |     x
-18 | |   }
-   | |___^
-note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3
-  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
-   |
-16 | /   fn foo<'a>(&self, x: &i32) -> &i32 {
-17 | |     x
-18 | |   }
-   | |___^
+   |     ^ ...but data from `x` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
index 43f00c32c62..cae45023e26 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
@@ -1,23 +1,12 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
    |
+16 |     fn foo<'a>(&self, x: &Foo) -> &Foo {
+   |                          ----     ----
+   |                          |
+   |                          this parameter and the return type are declared with different lifetimes...
 17 |         if true { x } else { self }
-   |                   ^
-   |
-note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5...
-  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
-   |
-16 | /     fn foo<'a>(&self, x: &Foo) -> &Foo {
-17 | |         if true { x } else { self }
-18 | |     }
-   | |_____^
-note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5
-  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
-   |
-16 | /     fn foo<'a>(&self, x: &Foo) -> &Foo {
-17 | |         if true { x } else { self }
-18 | |     }
-   | |_____^
+   |                   ^ ...but data from `x` is returned here
 
 error: aborting due to previous error
 
diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs
index dd7e8a869ec..465b4271035 100644
--- a/src/test/compile-fail/issue-16747.rs
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.rs
@@ -16,14 +16,16 @@ trait Collection { fn len(&self) -> usize; }
 
 struct List<'a, T: ListItem<'a>> {
     slice: &'a [T]
-//~^ ERROR the parameter type `T` may not live long enough
-//~| HELP consider adding an explicit lifetime bound
-//~| NOTE ...so that the reference type `&'a [T]` does not outlive the data it points at
 }
+
 impl<'a, T: ListItem<'a>> Collection for List<'a, T> {
     fn len(&self) -> usize {
         0
     }
 }
 
+struct Foo<T> {
+    foo: &'static T
+}
+
 fn main() {}
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
new file mode 100644
index 00000000000..e17a660c591
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -0,0 +1,30 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:18:5
+   |
+17 | struct List<'a, T: ListItem<'a>> {
+   |                 -- help: consider adding an explicit lifetime bound `T: 'a`...
+18 |     slice: &'a [T]
+   |     ^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'a [T]` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:18:5
+   |
+18 |     slice: &'a [T]
+   |     ^^^^^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5
+   |
+27 | struct Foo<T> {
+   |            - help: consider adding an explicit lifetime bound `T: 'static`...
+28 |     foo: &'static T
+   |     ^^^^^^^^^^^^^^^
+   |
+note: ...so that the reference type `&'static T` does not outlive the data it points at
+  --> $DIR/lifetime-doesnt-live-long-enough.rs:28:5
+   |
+28 |     foo: &'static T
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr
deleted file mode 100644
index 744e8c30939..00000000000
--- a/src/test/ui/mismatched_types/E0281.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements the trait `std::ops::Fn<(std::string::String,)>`, but the trait `std::ops::Fn<(usize,)>` is required
-  --> $DIR/E0281.rs:14:5
-   |
-14 |     foo(|y: String| { });
-   |     ^^^ --------------- implements `std::ops::Fn<(std::string::String,)>`
-   |     |
-   |     expected usize, found struct `std::string::String`
-   |     requires `std::ops::Fn<(usize,)>`
-   |
-   = note: required by `foo`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/mismatched_types/E0631.rs b/src/test/ui/mismatched_types/E0631.rs
new file mode 100644
index 00000000000..e28f15ab0b6
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0631.rs
@@ -0,0 +1,21 @@
+// 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(unboxed_closures)]
+
+fn foo<F: Fn(usize)>(_: F) {}
+fn bar<F: Fn<usize>>(_: F) {}
+fn main() {
+    fn f(_: u64) {}
+    foo(|_: isize| {});
+    bar(|_: isize| {});
+    foo(f);
+    bar(f);
+}
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
new file mode 100644
index 00000000000..235e7a10063
--- /dev/null
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -0,0 +1,44 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/E0631.rs:17:5
+   |
+17 |     foo(|_: isize| {});
+   |     ^^^ ------------- found signature of `fn(isize) -> _`
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |
+   = note: required by `foo`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/E0631.rs:18:5
+   |
+18 |     bar(|_: isize| {});
+   |     ^^^ ------------- found signature of `fn(isize) -> _`
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |
+   = note: required by `bar`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/E0631.rs:19:5
+   |
+19 |     foo(f);
+   |     ^^^
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |     found signature of `fn(u64) -> _`
+   |
+   = note: required by `foo`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/E0631.rs:20:5
+   |
+20 |     bar(f);
+   |     ^^^
+   |     |
+   |     expected signature of `fn(usize) -> _`
+   |     found signature of `fn(u64) -> _`
+   |
+   = note: required by `bar`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs
index 284f82d86eb..f94471a73ca 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.rs
+++ b/src/test/ui/mismatched_types/closure-arg-count.rs
@@ -8,8 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
+fn f<F: Fn<usize>>(_: F) {}
 fn main() {
     [1, 2, 3].sort_by(|| panic!());
     [1, 2, 3].sort_by(|tuple| panic!());
     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+    f(|| panic!());
 }
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index ca71154e872..3031a77b1e8 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -1,35 +1,45 @@
 error[E0593]: closure takes 0 arguments but 2 arguments are required
-  --> $DIR/closure-arg-count.rs:12:15
+  --> $DIR/closure-arg-count.rs:15:15
    |
-12 |     [1, 2, 3].sort_by(|| panic!());
+15 |     [1, 2, 3].sort_by(|| panic!());
    |               ^^^^^^^ ----------- takes 0 arguments
    |               |
    |               expected closure that takes 2 arguments
 
 error[E0593]: closure takes 1 argument but 2 arguments are required
-  --> $DIR/closure-arg-count.rs:13:15
+  --> $DIR/closure-arg-count.rs:16:15
    |
-13 |     [1, 2, 3].sort_by(|tuple| panic!());
+16 |     [1, 2, 3].sort_by(|tuple| panic!());
    |               ^^^^^^^ ---------------- takes 1 argument
    |               |
    |               expected closure that takes 2 arguments
 
 error[E0308]: mismatched types
-  --> $DIR/closure-arg-count.rs:14:24
+  --> $DIR/closure-arg-count.rs:17:24
    |
-14 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+17 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
    |                        ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
    |
    = note: expected type `&{integer}`
               found type `(_, _)`
 
 error[E0593]: closure takes 1 argument but 2 arguments are required
-  --> $DIR/closure-arg-count.rs:14:15
+  --> $DIR/closure-arg-count.rs:17:15
    |
-14 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
+17 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
    |               ^^^^^^^ -------------------------- takes 1 argument
    |               |
    |               expected closure that takes 2 arguments
 
-error: aborting due to 4 previous errors
+error[E0593]: closure takes 0 arguments but 1 argument is required
+  --> $DIR/closure-arg-count.rs:18:5
+   |
+18 |     f(|| panic!());
+   |     ^ ----------- takes 0 arguments
+   |     |
+   |     expected closure that takes 1 argument
+   |
+   = note: required by `f`
+
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
new file mode 100644
index 00000000000..aa9dba4c3f4
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs
@@ -0,0 +1,21 @@
+// 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 a = [(1u32, 2u32)];
+    a.iter().map(|_: (u32, u32)| 45);
+    a.iter().map(|_: &(u16, u16)| 45);
+    a.iter().map(|_: (u16, u16)| 45);
+}
+
+fn baz<F: Fn(*mut &u32)>(_: F) {}
+fn _test<'a>(f: fn(*mut &'a u32)) {
+    baz(f);
+}
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
new file mode 100644
index 00000000000..866a024ab08
--- /dev/null
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -0,0 +1,45 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:13:14
+   |
+13 |     a.iter().map(|_: (u32, u32)| 45);
+   |              ^^^ ------------------ found signature of `fn((u32, u32)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:14:14
+   |
+14 |     a.iter().map(|_: &(u16, u16)| 45);
+   |              ^^^ ------------------- found signature of `for<'r> fn(&'r (u16, u16)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/closure-arg-type-mismatch.rs:15:14
+   |
+15 |     a.iter().map(|_: (u16, u16)| 45);
+   |              ^^^ ------------------ found signature of `fn((u16, u16)) -> _`
+   |              |
+   |              expected signature of `fn(&(u32, u32)) -> _`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/closure-arg-type-mismatch.rs:20:5
+   |
+20 |     baz(f);
+   |     ^^^
+   |     |
+   |     expected signature of `for<'r> fn(*mut &'r u32) -> _`
+   |     found signature of `fn(*mut &'a u32) -> _`
+   |
+   = note: required by `baz`
+
+error[E0271]: type mismatch resolving `for<'r> <fn(*mut &'a u32) as std::ops::FnOnce<(*mut &'r u32,)>>::Output == ()`
+  --> $DIR/closure-arg-type-mismatch.rs:20:5
+   |
+20 |     baz(f);
+   |     ^^^ expected bound lifetime parameter, found concrete lifetime
+   |
+   = note: required by `baz`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index d928a6a0a8e..a54fd118cc5 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -7,14 +7,13 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
    = note: required by `baz`
 
-error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required
+error[E0631]: type mismatch in closure arguments
   --> $DIR/closure-mismatch.rs:18:5
    |
 18 |     baz(|_| ());
-   |     ^^^ ------ implements `std::ops::Fn<(_,)>`
+   |     ^^^ ------ found signature of `fn(_) -> _`
    |     |
-   |     expected concrete lifetime, found bound lifetime parameter
-   |     requires `for<'r> std::ops::Fn<(&'r (),)>`
+   |     expected signature of `for<'r> fn(&'r ()) -> _`
    |
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
    = note: required by `baz`
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 120fb87cdc8..09a90ef3d6b 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -1,16 +1,22 @@
-error[E0281]: type mismatch: `fn(&mut isize) {takes_mut}` implements the trait `for<'r> std::ops::FnOnce<(&'r mut isize,)>`, but the trait `std::ops::FnOnce<(&{integer},)>` is required
+error[E0631]: type mismatch in function arguments
   --> $DIR/fn-variance-1.rs:21:5
    |
 21 |     apply(&3, takes_mut);
-   |     ^^^^^ types differ in mutability
+   |     ^^^^^
+   |     |
+   |     expected signature of `fn(&{integer}) -> _`
+   |     found signature of `for<'r> fn(&'r mut isize) -> _`
    |
    = note: required by `apply`
 
-error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for<'r> std::ops::FnOnce<(&'r isize,)>`, but the trait `std::ops::FnOnce<(&mut {integer},)>` is required
+error[E0631]: type mismatch in function arguments
   --> $DIR/fn-variance-1.rs:27:5
    |
 27 |     apply(&mut 3, takes_imm);
-   |     ^^^^^ types differ in mutability
+   |     ^^^^^
+   |     |
+   |     expected signature of `fn(&mut {integer}) -> _`
+   |     found signature of `for<'r> fn(&'r isize) -> _`
    |
    = note: required by `apply`
 
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index e2e2019307f..71a3a0a5714 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -8,14 +8,13 @@ error[E0599]: no method named `count` found for type `std::iter::Filter<std::ite
            `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
            `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:17:39: 17:53]> : std::iter::Iterator`
 
-error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` implements the trait `for<'r> std::ops::FnMut<(&'r str,)>`, but the trait `for<'r> std::ops::FnMut<(&'r &str,)>` is required
+error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:17:32
    |
 17 |     once::<&str>("str").fuse().filter(|a: &str| true).count();
-   |                                ^^^^^^ -------------- implements `for<'r> std::ops::FnMut<(&'r str,)>`
+   |                                ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`
    |                                |
-   |                                expected &str, found str
-   |                                requires `for<'r> std::ops::FnMut<(&'r &str,)>`
+   |                                expected signature of `for<'r> fn(&'r &str) -> _`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index f14e711b23a..59883649280 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -1,14 +1,11 @@
-error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:22:23: 22:73]` implements the trait `std::ops::FnMut<(usize, isize)>`, but the trait `std::ops::FnMut<(isize, isize)>` is required
+error[E0631]: type mismatch in closure arguments
   --> $DIR/unboxed-closures-vtable-mismatch.rs:25:13
    |
 22 |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
-   |                       -------------------------------------------------- implements `std::ops::FnMut<(usize, isize)>`
+   |                       -------------------------------------------------- found signature of `fn(usize, isize) -> _`
 ...
 25 |     let z = call_it(3, f);
-   |             ^^^^^^^
-   |             |
-   |             expected isize, found usize
-   |             requires `std::ops::FnMut<(isize, isize)>`
+   |             ^^^^^^^ expected signature of `fn(isize, isize) -> _`
    |
    = note: required by `call_it`
 
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
index 9936a1eb81e..1d4ab35046b 100644
--- a/src/test/ui/path-lookahead.stderr
+++ b/src/test/ui/path-lookahead.stderr
@@ -9,10 +9,8 @@ warning: unnecessary parentheses around `return` value
 warning: function is never used: `with_parens`
   --> $DIR/path-lookahead.rs:17:1
    |
-17 | / fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
-18 | |   return (<T as ToString>::to_string(&arg)); //~WARN unnecessary parentheses around `return` value
-19 | | }
-   | |_^
+17 | fn with_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `with_parens`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
   --> $DIR/path-lookahead.rs:13:9
@@ -24,8 +22,6 @@ note: lint level defined here
 warning: function is never used: `no_parens`
   --> $DIR/path-lookahead.rs:21:1
    |
-21 | / fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
-22 | |   return <T as ToString>::to_string(&arg);
-23 | | }
-   | |_^
+21 | fn no_parens<T: ToString>(arg: T) -> String { //~WARN function is never used: `no_parens`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index ee1481ec6f2..f7e5c602644 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -10,7 +10,7 @@ error[E0423]: expected value, found struct `Z`
    |
 help: possible better candidate is found in another module, you can import it into scope
    |
-16 |     use m::n::Z;
+22 |     use m::n::Z;
    |
 
 error[E0423]: expected value, found struct `S`
@@ -24,7 +24,7 @@ error[E0423]: expected value, found struct `S`
    |
 help: possible better candidate is found in another module, you can import it into scope
    |
-15 | use m::S;
+32 | use m::S;
    |
 
 error[E0423]: expected value, found struct `xcrate::S`
@@ -38,7 +38,7 @@ error[E0423]: expected value, found struct `xcrate::S`
    |
 help: possible better candidate is found in another module, you can import it into scope
    |
-15 | use m::S;
+32 | use m::S;
    |
 
 error[E0603]: tuple struct `Z` is private
diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs
index e0027fed4d6..a43b8fc99df 100644
--- a/src/test/ui/resolve/use_suggestion_placement.rs
+++ b/src/test/ui/resolve/use_suggestion_placement.rs
@@ -16,6 +16,15 @@ mod m {
     pub const A: i32 = 0;
 }
 
+mod foo {
+    #[derive(Debug)]
+    pub struct Foo;
+
+    // test whether the use suggestion isn't
+    // placed into the expansion of `#[derive(Debug)]
+    type Bar = Path;
+}
+
 fn main() {
     y!();
     let _ = A;
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
index 5c74d8bed66..8a4dfdc8027 100644
--- a/src/test/ui/resolve/use_suggestion_placement.stderr
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -1,7 +1,18 @@
+error[E0412]: cannot find type `Path` in this scope
+  --> $DIR/use_suggestion_placement.rs:25:16
+   |
+25 |     type Bar = Path;
+   |                ^^^^ not found in this scope
+   |
+help: possible candidate is found in another module, you can import it into scope
+   |
+21 |     use std::path::Path;
+   |
+
 error[E0425]: cannot find value `A` in this scope
-  --> $DIR/use_suggestion_placement.rs:21:13
+  --> $DIR/use_suggestion_placement.rs:30:13
    |
-21 |     let _ = A;
+30 |     let _ = A;
    |             ^ not found in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
@@ -10,9 +21,9 @@ help: possible candidate is found in another module, you can import it into scop
    |
 
 error[E0412]: cannot find type `HashMap` in this scope
-  --> $DIR/use_suggestion_placement.rs:26:23
+  --> $DIR/use_suggestion_placement.rs:35:23
    |
-26 |     type Dict<K, V> = HashMap<K, V>;
+35 |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
    |
 help: possible candidates are found in other modules, you can import them into scope
@@ -23,16 +34,16 @@ help: possible candidates are found in other modules, you can import them into s
    |
 
 error[E0091]: type parameter `K` is unused
-  --> $DIR/use_suggestion_placement.rs:26:15
+  --> $DIR/use_suggestion_placement.rs:35:15
    |
-26 |     type Dict<K, V> = HashMap<K, V>;
+35 |     type Dict<K, V> = HashMap<K, V>;
    |               ^ unused type parameter
 
 error[E0091]: type parameter `V` is unused
-  --> $DIR/use_suggestion_placement.rs:26:18
+  --> $DIR/use_suggestion_placement.rs:35:18
    |
-26 |     type Dict<K, V> = HashMap<K, V>;
+35 |     type Dict<K, V> = HashMap<K, V>;
    |                  ^ unused type parameter
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs
index 7eb4c32972a..3741ba4f3ae 100644
--- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs
+++ b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs
@@ -11,6 +11,7 @@
 #![feature(fn_must_use)]
 #![warn(unused_must_use)]
 
+#[derive(PartialEq, Eq)]
 struct MyStruct {
     n: usize,
 }
@@ -58,13 +59,18 @@ fn main() {
     need_to_use_this_value();
 
     let mut m = MyStruct { n: 2 };
+    let n = MyStruct { n: 3 };
+
     m.need_to_use_this_method_value();
     m.is_even(); // trait method!
 
-    m.replace(3);
+    m.replace(3); // won't warn (annotation needs to be in trait definition)
 
+    // comparison methods are `must_use`
     2.eq(&3);
+    m.eq(&n);
 
-    // FIXME: operators should probably be `must_use` if underlying method is
+    // lint includes comparison operators
     2 == 3;
+    m == n;
 }
diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr
index 69755c89b48..fdd0a591bc7 100644
--- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr
+++ b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr
@@ -1,7 +1,7 @@
 warning: unused return value of `need_to_use_this_value` which must be used: it's important
-  --> $DIR/fn_must_use.rs:58:5
+  --> $DIR/fn_must_use.rs:59:5
    |
-58 |     need_to_use_this_value();
+59 |     need_to_use_this_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
@@ -11,20 +11,38 @@ note: lint level defined here
    |         ^^^^^^^^^^^^^^^
 
 warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
-  --> $DIR/fn_must_use.rs:61:5
+  --> $DIR/fn_must_use.rs:64:5
    |
-61 |     m.need_to_use_this_method_value();
+64 |     m.need_to_use_this_method_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused return value of `EvenNature::is_even` which must be used: no side effects
-  --> $DIR/fn_must_use.rs:62:5
+  --> $DIR/fn_must_use.rs:65:5
    |
-62 |     m.is_even(); // trait method!
+65 |     m.is_even(); // trait method!
    |     ^^^^^^^^^^^^
 
 warning: unused return value of `std::cmp::PartialEq::eq` which must be used
-  --> $DIR/fn_must_use.rs:66:5
+  --> $DIR/fn_must_use.rs:70:5
    |
-66 |     2.eq(&3);
+70 |     2.eq(&3);
    |     ^^^^^^^^^
 
+warning: unused return value of `std::cmp::PartialEq::eq` which must be used
+  --> $DIR/fn_must_use.rs:71:5
+   |
+71 |     m.eq(&n);
+   |     ^^^^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/fn_must_use.rs:74:5
+   |
+74 |     2 == 3;
+   |     ^^^^^^
+
+warning: unused comparison which must be used
+  --> $DIR/fn_must_use.rs:75:5
+   |
+75 |     m == n;
+   |     ^^^^^^
+
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index 0cd7e1046f6..b57b58e3d2a 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -6,7 +6,7 @@ error[E0404]: expected trait, found type parameter `Add`
    |
 help: possible better candidate is found in another module, you can import it into scope
    |
-11 | use std::ops::Add;
+13 | use std::ops::Add;
    |
 
 error[E0601]: main function not found
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
new file mode 100644
index 00000000000..cf2a4b8d037
--- /dev/null
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.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.
+
+#![allow(dead_code)]
+
+#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+struct DerivedOn;
+
+fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
new file mode 100644
index 00000000000..a0485bed2f4
--- /dev/null
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
@@ -0,0 +1,8 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43927-non-ADT-derive.rs:13:1
+   |
+13 | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug, PartialEq, Eq)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/unused-warning-point-at-signature.rs b/src/test/ui/span/unused-warning-point-at-signature.rs
new file mode 100644
index 00000000000..eb659d08da0
--- /dev/null
+++ b/src/test/ui/span/unused-warning-point-at-signature.rs
@@ -0,0 +1,40 @@
+// 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.
+
+// run-pass
+
+#![warn(unused)]
+
+enum Enum {
+    A,
+    B,
+    C,
+    D,
+}
+
+struct Struct {
+    a: usize,
+    b: usize,
+    c: usize,
+    d: usize,
+}
+
+fn func() -> usize {
+    3
+}
+
+fn
+func_complete_span()
+-> usize
+{
+    3
+}
+
+fn main() {}
diff --git a/src/test/ui/span/unused-warning-point-at-signature.stderr b/src/test/ui/span/unused-warning-point-at-signature.stderr
new file mode 100644
index 00000000000..8e658670e9c
--- /dev/null
+++ b/src/test/ui/span/unused-warning-point-at-signature.stderr
@@ -0,0 +1,36 @@
+warning: enum is never used: `Enum`
+  --> $DIR/unused-warning-point-at-signature.rs:15:1
+   |
+15 | enum Enum {
+   | ^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/unused-warning-point-at-signature.rs:13:9
+   |
+13 | #![warn(unused)]
+   |         ^^^^^^
+   = note: #[warn(dead_code)] implied by #[warn(unused)]
+
+warning: struct is never used: `Struct`
+  --> $DIR/unused-warning-point-at-signature.rs:22:1
+   |
+22 | struct Struct {
+   | ^^^^^^^^^^^^^
+
+warning: function is never used: `func`
+  --> $DIR/unused-warning-point-at-signature.rs:29:1
+   |
+29 | fn func() -> usize {
+   | ^^^^^^^^^^^^^^^^^^
+
+warning: function is never used: `func_complete_span`
+  --> $DIR/unused-warning-point-at-signature.rs:33:1
+   |
+33 | / fn
+34 | | func_complete_span()
+35 | | -> usize
+36 | | {
+37 | |     3
+38 | | }
+   | |_^
+
diff --git a/src/test/ui/suggestions/suggest-methods.rs b/src/test/ui/suggestions/suggest-methods.rs
new file mode 100644
index 00000000000..b02881dc7ee
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-methods.rs
@@ -0,0 +1,40 @@
+// 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;
+
+impl Foo {
+    fn bar(self) {}
+    fn baz(&self, x: f64) {}
+}
+
+trait FooT {
+    fn bag(&self);
+}
+
+impl FooT for Foo {
+    fn bag(&self) {}
+}
+
+fn main() {
+    let f = Foo;
+    f.bat(1.0);
+
+    let s = "foo".to_string();
+    let _ = s.is_emtpy();
+
+    // Generates a warning for `count_zeros()`. `count_ones()` is also a close
+    // match, but the former is closer.
+    let _ = 63u32.count_eos();
+
+    // Does not generate a warning
+    let _ = 63u32.count_o();
+
+}
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
new file mode 100644
index 00000000000..41beb73b1bc
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -0,0 +1,32 @@
+error[E0599]: no method named `bat` found for type `Foo` in the current scope
+  --> $DIR/suggest-methods.rs:28:7
+   |
+28 |     f.bat(1.0);
+   |       ^^^
+   |
+   = help: did you mean `bar`?
+
+error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
+  --> $DIR/suggest-methods.rs:31:15
+   |
+31 |     let _ = s.is_emtpy();
+   |               ^^^^^^^^
+   |
+   = help: did you mean `is_empty`?
+
+error[E0599]: no method named `count_eos` found for type `u32` in the current scope
+  --> $DIR/suggest-methods.rs:35:19
+   |
+35 |     let _ = 63u32.count_eos();
+   |                   ^^^^^^^^^
+   |
+   = help: did you mean `count_zeros`?
+
+error[E0599]: no method named `count_o` found for type `u32` in the current scope
+  --> $DIR/suggest-methods.rs:38:19
+   |
+38 |     let _ = 63u32.count_o();
+   |                   ^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/suggestions/try-on-option.rs b/src/test/ui/suggestions/try-on-option.rs
new file mode 100644
index 00000000000..4cd8cd81151
--- /dev/null
+++ b/src/test/ui/suggestions/try-on-option.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(try_trait)]
+
+fn main() {}
+
+fn foo() -> Result<u32, ()> {
+    let x: Option<u32> = None;
+    x?;
+    Ok(22)
+}
+
+fn bar() -> u32 {
+    let x: Option<u32> = None;
+    x?;
+    22
+}
diff --git a/src/test/ui/suggestions/try-on-option.stderr b/src/test/ui/suggestions/try-on-option.stderr
new file mode 100644
index 00000000000..86d4510cad3
--- /dev/null
+++ b/src/test/ui/suggestions/try-on-option.stderr
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `(): std::convert::From<std::option::NoneError>` is not satisfied
+  --> $DIR/try-on-option.rs:17:5
+   |
+17 |     x?;
+   |     ^^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
+   |
+   = note: required by `std::convert::From::from`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
+  --> $DIR/try-on-option.rs:23:5
+   |
+23 |     x?;
+   |     --
+   |     |
+   |     cannot use the `?` operator in a function that returns `u32`
+   |     in this macro invocation
+   |
+   = help: the trait `std::ops::Try` is not implemented for `u32`
+   = note: required by `std::ops::Try::from_error`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/type-check/issue-41314.rs b/src/test/ui/type-check/issue-41314.rs
new file mode 100644
index 00000000000..5127a8ce174
--- /dev/null
+++ b/src/test/ui/type-check/issue-41314.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.
+
+enum X {
+    Y(u32)
+}
+
+fn main() {
+    match X::Y(0) {
+        X::Y { number } => {}
+    }
+}
diff --git a/src/test/ui/type-check/issue-41314.stderr b/src/test/ui/type-check/issue-41314.stderr
new file mode 100644
index 00000000000..acae7a35087
--- /dev/null
+++ b/src/test/ui/type-check/issue-41314.stderr
@@ -0,0 +1,16 @@
+error[E0026]: variant `X::Y` does not have a field named `number`
+  --> $DIR/issue-41314.rs:17:16
+   |
+17 |         X::Y { number } => {}
+   |                ^^^^^^ variant `X::Y` does not have field `number`
+
+error[E0027]: pattern does not mention field `0`
+  --> $DIR/issue-41314.rs:17:9
+   |
+17 |         X::Y { number } => {}
+   |         ^^^^^^^^^^^^^^^ missing field `0`
+   |
+   = note: trying to match a tuple variant with a struct variant pattern
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 0e91fa9c602..db957a7a0fc 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -50,6 +50,7 @@ static TARGETS: &'static [&'static str] = &[
     "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-linux-gnu",
+    "aarch64-unknown-linux-musl",
     "arm-linux-androideabi",
     "arm-unknown-linux-gnueabi",
     "arm-unknown-linux-gnueabihf",
@@ -108,6 +109,7 @@ struct Manifest {
     manifest_version: String,
     date: String,
     pkg: BTreeMap<String, Package>,
+    renames: BTreeMap<String, Rename>
 }
 
 #[derive(Serialize)]
@@ -118,6 +120,11 @@ struct Package {
 }
 
 #[derive(Serialize)]
+struct Rename {
+    to: String,
+}
+
+#[derive(Serialize)]
 struct Target {
     available: bool,
     url: Option<String>,
@@ -236,6 +243,7 @@ impl Builder {
             manifest_version: "2".to_string(),
             date: self.date.to_string(),
             pkg: BTreeMap::new(),
+            renames: BTreeMap::new(),
         };
 
         self.package("rustc", &mut manifest.pkg, HOSTS);
@@ -244,14 +252,11 @@ impl Builder {
         self.package("rust-std", &mut manifest.pkg, TARGETS);
         self.package("rust-docs", &mut manifest.pkg, TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
-        let rls_package_name = if self.rust_release == "nightly" {
-            "rls"
-        } else {
-            "rls-preview"
-        };
-        self.package(rls_package_name, &mut manifest.pkg, HOSTS);
+        self.package("rls-preview", &mut manifest.pkg, HOSTS);
         self.package("rust-analysis", &mut manifest.pkg, TARGETS);
 
+        manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
+
         let mut pkg = Package {
             version: self.cached_version("rust").to_string(),
             git_commit_hash: self.cached_git_commit_hash("rust").clone(),
@@ -287,7 +292,7 @@ impl Builder {
             }
 
             extensions.push(Component {
-                pkg: rls_package_name.to_string(),
+                pkg: "rls-preview".to_string(),
                 target: host.to_string(),
             });
             extensions.push(Component {
@@ -319,7 +324,7 @@ impl Builder {
         }
         manifest.pkg.insert("rust".to_string(), pkg);
 
-        return manifest
+        return manifest;
     }
 
     fn package(&mut self,
@@ -452,6 +457,7 @@ impl Builder {
         cmd.arg("--no-tty")
             .arg("--yes")
             .arg("--passphrase-fd").arg("0")
+            .arg("--personal-digest-preferences").arg("SHA512")
             .arg("--armor")
             .arg("--output").arg(&asc)
             .arg("--detach-sign").arg(path)
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 8118b02ac5ce49b22e049ff03316d5e1574852c
+Subproject e447ac7e94b7f56ab13e361f9e324dafe3eb0a3
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 012ee835494..0a9da26d996 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -49,7 +49,7 @@ const TEST_REPOS: &'static [Test] = &[
     Test {
         name: "xsv",
         repo: "https://github.com/BurntSushi/xsv",
-        sha: "a9a7163f2a2953cea426fee1216bec914fe2f56a",
+        sha: "4b308adbe48ac81657fd124b90b44f7c3263f771",
         lock: None,
     },
 ];
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 7221e38023c41ff2532ebbf54a7da296fd488b5
+Subproject 93b47d14cef5720bba7cfb4dcb8078fbf1f706c
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
-Subproject a1fd68da464fc51585f351c81fc2b867211c197
+Subproject 22eb5241c0ee5bb7eaf95e270a2b1500e82bf76
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e9e4b55402c..38df6577694 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -35,8 +35,11 @@ static EXCEPTIONS: &'static [&'static str] = &[
     "thread-id", // Apache-2.0, mdbook
     "cssparser", // MPL-2.0, rustdoc
     "smallvec", // MPL-2.0, rustdoc
+    // FIXME: remove magenta references when "everything" has moved over to using the zircon name.
     "magenta-sys", // BSD-3-Clause, rustdoc
     "magenta", // BSD-3-Clause, rustdoc
+    "zircon-sys", // BSD-3-Clause, rustdoc
+    "zircon", // BSD-3-Clause, rustdoc
     "cssparser-macros", // MPL-2.0, rustdoc
     "selectors", // MPL-2.0, rustdoc
 ];
diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml
index 707b316190d..1700daa0aff 100644
--- a/src/tools/toolstate.toml
+++ b/src/tools/toolstate.toml
@@ -23,7 +23,14 @@
 # Each tool has a list of people to ping
 
 # ping @oli-obk @RalfJung @eddyb
-miri = "Testing"
+miri = "Broken"
 
 # ping @Manishearth @llogiq @mcarton @oli-obk
 clippy = "Broken"
+
+# ping @nrc
+rls = "Testing"
+
+# ping @nrc
+rustfmt = "Testing"
+