about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--README.md2
-rw-r--r--RELEASES.md7
-rw-r--r--appveyor.yml5
-rw-r--r--config.toml.example37
-rwxr-xr-xconfigure782
-rw-r--r--src/Cargo.lock239
-rw-r--r--src/Cargo.toml5
-rw-r--r--src/bootstrap/README.md37
-rw-r--r--src/bootstrap/bin/rustc.rs10
-rw-r--r--src/bootstrap/bootstrap.py336
-rw-r--r--src/bootstrap/builder.rs16
-rw-r--r--src/bootstrap/check.rs6
-rw-r--r--src/bootstrap/compile.rs60
-rw-r--r--src/bootstrap/config.rs311
-rwxr-xr-xsrc/bootstrap/configure.py408
-rw-r--r--src/bootstrap/dist.rs1
-rw-r--r--src/bootstrap/doc.rs49
-rw-r--r--src/bootstrap/flags.rs14
-rw-r--r--src/bootstrap/lib.rs26
-rw-r--r--src/bootstrap/metadata.rs4
-rw-r--r--src/bootstrap/mk/Makefile.in2
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/bootstrap/sanity.rs34
-rw-r--r--src/ci/docker/arm-android/Dockerfile5
-rw-r--r--src/ci/docker/armhf-gnu/Dockerfile5
-rw-r--r--src/ci/docker/asmjs/Dockerfile5
-rw-r--r--src/ci/docker/cross/Dockerfile12
-rwxr-xr-x[-rw-r--r--]src/ci/docker/cross/install-x86_64-redox.sh (renamed from src/ci/docker/scripts/dumb-init.sh)14
-rw-r--r--src/ci/docker/disabled/aarch64-gnu/Dockerfile5
-rw-r--r--src/ci/docker/disabled/dist-aarch64-android/Dockerfile5
-rw-r--r--src/ci/docker/disabled/dist-armv7-android/Dockerfile5
-rw-r--r--src/ci/docker/disabled/dist-i686-android/Dockerfile5
-rw-r--r--src/ci/docker/disabled/dist-x86_64-android/Dockerfile5
-rw-r--r--src/ci/docker/disabled/dist-x86_64-redox/Dockerfile22
-rw-r--r--src/ci/docker/disabled/wasm32-exp/Dockerfile7
-rw-r--r--src/ci/docker/disabled/wasm32/Dockerfile5
-rw-r--r--src/ci/docker/dist-aarch64-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-android/Dockerfile5
-rw-r--r--src/ci/docker/dist-arm-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-armhf-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-armv7-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-fuchsia/Dockerfile5
-rw-r--r--src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile5
-rw-r--r--src/ci/docker/dist-i686-freebsd/Dockerfile5
-rw-r--r--src/ci/docker/dist-i686-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-mips-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-mips64-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-mips64el-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-mipsel-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-powerpc-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-powerpc64-linux/Dockerfile4
-rw-r--r--src/ci/docker/dist-powerpc64le-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-s390x-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-x86_64-freebsd/Dockerfile5
-rw-r--r--src/ci/docker/dist-x86_64-linux/Dockerfile5
-rw-r--r--src/ci/docker/dist-x86_64-musl/Dockerfile5
-rw-r--r--src/ci/docker/dist-x86_64-netbsd/Dockerfile5
-rw-r--r--src/ci/docker/i686-gnu-nopt/Dockerfile5
-rw-r--r--src/ci/docker/i686-gnu/Dockerfile5
-rwxr-xr-xsrc/ci/docker/run.sh1
-rw-r--r--src/ci/docker/x86_64-gnu-aux/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-debug/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-distcheck/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-incremental/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu-nopt/Dockerfile5
-rw-r--r--src/ci/docker/x86_64-gnu/Dockerfile5
m---------src/doc/book0
m---------src/doc/nomicon0
m---------src/doc/reference0
-rw-r--r--src/doc/unstable-book/src/language-features/rvalue-static-promotion.md23
-rw-r--r--src/doc/unstable-book/src/library-features/string-retain.md23
-rw-r--r--src/etc/htmldocck.py33
-rw-r--r--src/etc/platform-intrinsics/powerpc.json35
m---------src/jemalloc0
-rw-r--r--src/liballoc/allocator.rs30
-rw-r--r--src/liballoc/arc.rs302
-rw-r--r--src/liballoc/binary_heap.rs6
-rw-r--r--src/liballoc/boxed.rs4
-rw-r--r--src/liballoc/btree/map.rs14
-rw-r--r--src/liballoc/btree/node.rs16
-rw-r--r--src/liballoc/fmt.rs2
-rw-r--r--src/liballoc/lib.rs4
-rw-r--r--src/liballoc/linked_list.rs4
-rw-r--r--src/liballoc/raw_vec.rs18
-rw-r--r--src/liballoc/rc.rs353
-rw-r--r--src/liballoc/slice.rs45
-rw-r--r--src/liballoc/str.rs2
-rw-r--r--src/liballoc/string.rs137
-rw-r--r--src/liballoc/tests/lib.rs7
-rw-r--r--src/liballoc/tests/string.rs20
-rw-r--r--src/liballoc/tests/vec.rs167
-rw-r--r--src/liballoc/vec.rs117
-rw-r--r--src/liballoc/vec_deque.rs8
-rw-r--r--src/liballoc_jemalloc/build.rs24
-rw-r--r--src/liballoc_jemalloc/lib.rs4
-rw-r--r--src/liballoc_system/lib.rs2
-rw-r--r--src/libarena/lib.rs3
-rw-r--r--src/libbacktrace/config.sub47
-rw-r--r--src/libcollections/lib.rs2
m---------src/libcompiler_builtins0
-rw-r--r--src/libcore/array.rs3
-rw-r--r--src/libcore/cell.rs6
-rw-r--r--src/libcore/clone.rs3
-rw-r--r--src/libcore/fmt/builders.rs32
-rw-r--r--src/libcore/fmt/mod.rs8
-rw-r--r--src/libcore/hash/mod.rs9
-rw-r--r--src/libcore/iter/iterator.rs2
-rw-r--r--src/libcore/iter/mod.rs10
-rw-r--r--src/libcore/iter/traits.rs2
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/mem.rs2
-rw-r--r--src/libcore/num/dec2flt/rawfp.rs6
-rw-r--r--src/libcore/num/diy_float.rs2
-rw-r--r--src/libcore/num/flt2dec/mod.rs6
-rw-r--r--src/libcore/ops/try.rs2
-rw-r--r--src/libcore/ptr.rs3
-rw-r--r--src/libcore/result.rs100
-rw-r--r--src/libcore/slice/mod.rs15
-rw-r--r--src/libcore/str/mod.rs2
-rw-r--r--src/libcore/str/pattern.rs22
-rw-r--r--src/libcore/sync/atomic.rs2
-rw-r--r--src/libcore/tests/iter.rs2
-rw-r--r--src/libcore/tests/lib.rs4
-rw-r--r--src/libcore/tests/option.rs2
-rw-r--r--src/libcore/tuple.rs1
-rw-r--r--src/libfmt_macros/lib.rs5
-rw-r--r--src/libgetopts/lib.rs29
-rw-r--r--src/libgraphviz/lib.rs21
-rw-r--r--src/libpanic_abort/lib.rs2
-rw-r--r--src/libpanic_unwind/gcc.rs2
-rw-r--r--src/libpanic_unwind/lib.rs7
-rw-r--r--src/libproc_macro/lib.rs11
-rw-r--r--src/libprofiler_builtins/lib.rs2
-rw-r--r--src/librand/distributions/gamma.rs6
-rw-r--r--src/librand/distributions/mod.rs2
-rw-r--r--src/librand/distributions/normal.rs4
-rw-r--r--src/librand/distributions/range.rs4
-rw-r--r--src/librand/isaac.rs4
-rw-r--r--src/librand/lib.rs12
-rw-r--r--src/librand/reseeding.rs8
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/dep_graph/edges.rs4
-rw-r--r--src/librustc/dep_graph/graph.rs15
-rw-r--r--src/librustc/diagnostics.rs19
-rw-r--r--src/librustc/hir/intravisit.rs25
-rw-r--r--src/librustc/hir/lowering.rs145
-rw-r--r--src/librustc/hir/map/collector.rs203
-rw-r--r--src/librustc/hir/map/mod.rs336
-rw-r--r--src/librustc/hir/mod.rs110
-rw-r--r--src/librustc/hir/print.rs90
-rw-r--r--src/librustc/ich/impls_hir.rs19
-rw-r--r--src/librustc/ich/impls_ty.rs4
-rw-r--r--src/librustc/infer/error_reporting/anon_anon_conflict.rs240
-rw-r--r--src/librustc/infer/error_reporting/mod.rs10
-rw-r--r--src/librustc/infer/error_reporting/named_anon_conflict.rs69
-rw-r--r--src/librustc/infer/error_reporting/util.rs156
-rw-r--r--src/librustc/infer/mod.rs2
-rw-r--r--src/librustc/infer/resolve.rs2
-rw-r--r--src/librustc/lib.rs8
-rw-r--r--src/librustc/lint/builtin.rs2
-rw-r--r--src/librustc/lint/context.rs10
-rw-r--r--src/librustc/lint/levels.rs65
-rw-r--r--src/librustc/middle/dead.rs4
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/middle/liveness.rs10
-rw-r--r--src/librustc/middle/mem_categorization.rs6
-rw-r--r--src/librustc/middle/region.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs39
-rw-r--r--src/librustc/middle/stability.rs12
-rw-r--r--src/librustc/mir/traversal.rs2
-rw-r--r--src/librustc/session/config.rs6
-rw-r--r--src/librustc/session/mod.rs32
-rw-r--r--src/librustc/traits/error_reporting.rs18
-rw-r--r--src/librustc/traits/fulfill.rs2
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/select.rs20
-rw-r--r--src/librustc/traits/structural_impls.rs8
-rw-r--r--src/librustc/ty/context.rs20
-rw-r--r--src/librustc/ty/inhabitedness/def_id_forest.rs2
-rw-r--r--src/librustc/ty/instance.rs26
-rw-r--r--src/librustc/ty/item_path.rs7
-rw-r--r--src/librustc/ty/maps.rs162
-rw-r--r--src/librustc/ty/mod.rs13
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/sty.rs6
-rw-r--r--src/librustc/ty/util.rs10
-rw-r--r--src/librustc/ty/wf.rs52
-rw-r--r--src/librustc/util/common.rs77
-rw-r--r--src/librustc_allocator/expand.rs8
-rw-r--r--src/librustc_allocator/lib.rs13
-rw-r--r--src/librustc_apfloat/ieee.rs126
-rw-r--r--src/librustc_apfloat/lib.rs1
-rw-r--r--src/librustc_back/dynamic_lib.rs36
-rw-r--r--src/librustc_back/lib.rs3
-rw-r--r--src/librustc_back/target/apple_ios_base.rs2
-rw-r--r--src/librustc_back/target/haiku_base.rs1
-rw-r--r--src/librustc_back/target/l4re_base.rs62
-rw-r--r--src/librustc_back/target/le32_unknown_nacl.rs4
-rw-r--r--src/librustc_back/target/linux_musl_base.rs9
-rw-r--r--src/librustc_back/target/mod.rs10
-rw-r--r--src/librustc_back/target/redox_base.rs3
-rw-r--r--src/librustc_back/target/wasm32_experimental_emscripten.rs2
-rw-r--r--src/librustc_back/target/wasm32_unknown_emscripten.rs2
-rw-r--r--src/librustc_back/target/windows_base.rs4
-rw-r--r--src/librustc_back/target/windows_msvc_base.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs2
-rw-r--r--src/librustc_back/tempdir.rs9
-rw-r--r--src/librustc_bitflags/lib.rs2
-rw-r--r--src/librustc_borrowck/Cargo.toml1
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs67
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs51
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/lifetime.rs8
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs30
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs29
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs8
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs60
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs63
-rw-r--r--src/librustc_borrowck/diagnostics.rs550
-rw-r--r--src/librustc_borrowck/lib.rs8
-rw-r--r--src/librustc_const_eval/_match.rs12
-rw-r--r--src/librustc_const_eval/check_match.rs2
-rw-r--r--src/librustc_const_eval/eval.rs2
-rw-r--r--src/librustc_const_eval/lib.rs5
-rw-r--r--src/librustc_const_eval/pattern.rs18
-rw-r--r--src/librustc_const_math/float.rs7
-rw-r--r--src/librustc_const_math/lib.rs3
-rw-r--r--src/librustc_data_structures/accumulate_vec.rs2
-rw-r--r--src/librustc_data_structures/array_vec.rs4
-rw-r--r--src/librustc_data_structures/bitvec.rs2
-rw-r--r--src/librustc_data_structures/blake2b.rs2
-rw-r--r--src/librustc_data_structures/control_flow_graph/dominators/mod.rs83
-rw-r--r--src/librustc_data_structures/control_flow_graph/iterate/mod.rs16
-rw-r--r--src/librustc_data_structures/control_flow_graph/iterate/test.rs20
-rw-r--r--src/librustc_data_structures/control_flow_graph/mod.rs3
-rw-r--r--src/librustc_data_structures/control_flow_graph/reachable/mod.rs62
-rw-r--r--src/librustc_data_structures/control_flow_graph/reachable/test.rs50
-rw-r--r--src/librustc_data_structures/control_flow_graph/test.rs2
-rw-r--r--src/librustc_data_structures/control_flow_graph/transpose.rs64
-rw-r--r--src/librustc_data_structures/fmt_wrap.rs31
-rw-r--r--src/librustc_data_structures/fx.rs6
-rw-r--r--src/librustc_data_structures/graph/mod.rs125
-rw-r--r--src/librustc_data_structures/graph/tests.rs81
-rw-r--r--src/librustc_data_structures/indexed_set.rs64
-rw-r--r--src/librustc_data_structures/ivar.rs71
-rw-r--r--src/librustc_data_structures/lib.rs7
-rw-r--r--src/librustc_data_structures/obligation_forest/mod.rs64
-rw-r--r--src/librustc_data_structures/small_vec.rs2
-rw-r--r--src/librustc_data_structures/unify/mod.rs11
-rw-r--r--src/librustc_driver/driver.rs40
-rw-r--r--src/librustc_driver/lib.rs17
-rw-r--r--src/librustc_driver/pretty.rs59
-rw-r--r--src/librustc_driver/profile/mod.rs316
-rw-r--r--src/librustc_driver/profile/trace.rs315
-rw-r--r--src/librustc_driver/target_features.rs16
-rw-r--r--src/librustc_errors/diagnostic.rs34
-rw-r--r--src/librustc_errors/diagnostic_builder.rs36
-rw-r--r--src/librustc_errors/emitter.rs14
-rw-r--r--src/librustc_errors/lib.rs80
-rw-r--r--src/librustc_errors/snippet.rs2
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs2
-rw-r--r--src/librustc_incremental/calculate_svh/mod.rs4
-rw-r--r--src/librustc_incremental/lib.rs4
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs14
-rw-r--r--src/librustc_incremental/persist/hash.rs4
-rw-r--r--src/librustc_incremental/persist/mod.rs1
-rw-r--r--src/librustc_incremental/persist/preds/compress/classify/mod.rs2
-rw-r--r--src/librustc_incremental/persist/preds/compress/construct.rs2
-rw-r--r--src/librustc_incremental/persist/preds/mod.rs4
-rw-r--r--src/librustc_incremental/persist/work_product.rs2
-rw-r--r--src/librustc_lint/lib.rs11
-rw-r--r--src/librustc_lint/unused.rs34
-rw-r--r--src/librustc_llvm/archive_ro.rs2
-rw-r--r--src/librustc_llvm/diagnostic.rs10
-rw-r--r--src/librustc_llvm/lib.rs17
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/astencode.rs2
-rw-r--r--src/librustc_metadata/creader.rs38
-rw-r--r--src/librustc_metadata/cstore.rs12
-rw-r--r--src/librustc_metadata/cstore_impl.rs6
-rw-r--r--src/librustc_metadata/decoder.rs12
-rw-r--r--src/librustc_metadata/encoder.rs58
-rw-r--r--src/librustc_metadata/index.rs26
-rw-r--r--src/librustc_metadata/index_builder.rs4
-rw-r--r--src/librustc_metadata/isolated_encoder.rs4
-rw-r--r--src/librustc_metadata/lib.rs6
-rw-r--r--src/librustc_metadata/locator.rs18
-rw-r--r--src/librustc_metadata/schema.rs8
-rw-r--r--src/librustc_mir/Cargo.toml1
-rw-r--r--src/librustc_mir/borrow_check.rs1258
-rw-r--r--src/librustc_mir/build/cfg.rs8
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs2
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs2
-rw-r--r--src/librustc_mir/build/expr/into.rs4
-rw-r--r--src/librustc_mir/build/expr/stmt.rs6
-rw-r--r--src/librustc_mir/build/matches/mod.rs12
-rw-r--r--src/librustc_mir/build/matches/simplify.rs4
-rw-r--r--src/librustc_mir/build/matches/test.rs8
-rw-r--r--src/librustc_mir/build/matches/util.rs8
-rw-r--r--src/librustc_mir/build/misc.rs6
-rw-r--r--src/librustc_mir/build/mod.rs16
-rw-r--r--src/librustc_mir/build/scope.rs42
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs72
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs50
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs180
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs198
-rw-r--r--src/librustc_mir/dataflow/mod.rs279
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs6
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs332
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs324
-rw-r--r--src/librustc_mir/diagnostics.rs551
-rw-r--r--src/librustc_mir/hair/cx/block.rs18
-rw-r--r--src/librustc_mir/hair/cx/expr.rs66
-rw-r--r--src/librustc_mir/lib.rs10
-rw-r--r--src/librustc_mir/shim.rs400
-rw-r--r--src/librustc_mir/transform/add_call_guards.rs2
-rw-r--r--src/librustc_mir/transform/copy_prop.rs4
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs16
-rw-r--r--src/librustc_mir/transform/erase_regions.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs25
-rw-r--r--src/librustc_mir/transform/instcombine.rs4
-rw-r--r--src/librustc_mir/transform/mod.rs13
-rw-r--r--src/librustc_mir/transform/nll.rs2
-rw-r--r--src/librustc_mir/transform/promote_consts.rs20
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs12
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs4
-rw-r--r--src/librustc_mir/transform/simplify.rs4
-rw-r--r--src/librustc_mir/transform/type_check.rs16
-rw-r--r--src/librustc_mir/util/borrowck_errors.rs192
-rw-r--r--src/librustc_mir/util/def_use.rs12
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs4
-rw-r--r--src/librustc_mir/util/mod.rs1
-rw-r--r--src/librustc_mir/util/patch.rs2
-rw-r--r--src/librustc_passes/ast_validation.rs8
-rw-r--r--src/librustc_passes/consts.rs2
-rw-r--r--src/librustc_passes/lib.rs7
-rw-r--r--src/librustc_passes/loops.rs2
-rw-r--r--src/librustc_passes/mir_stats.rs39
-rw-r--r--src/librustc_passes/static_recursion.rs4
-rw-r--r--src/librustc_platform_intrinsics/lib.rs3
-rw-r--r--src/librustc_platform_intrinsics/powerpc.rs55
-rw-r--r--src/librustc_plugin/lib.rs6
-rw-r--r--src/librustc_plugin/load.rs6
-rw-r--r--src/librustc_plugin/registry.rs4
-rw-r--r--src/librustc_privacy/lib.rs23
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs14
-rw-r--r--src/librustc_resolve/check_unused.rs6
-rw-r--r--src/librustc_resolve/lib.rs200
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/librustc_resolve/resolve_imports.rs22
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs6
-rw-r--r--src/librustc_save_analysis/lib.rs22
-rw-r--r--src/librustc_save_analysis/sig.rs10
-rw-r--r--src/librustc_save_analysis/span_utils.rs2
-rw-r--r--src/librustc_trans/abi.rs8
-rw-r--r--src/librustc_trans/attributes.rs2
-rw-r--r--src/librustc_trans/back/archive.rs8
-rw-r--r--src/librustc_trans/back/link.rs18
-rw-r--r--src/librustc_trans/back/linker.rs26
-rw-r--r--src/librustc_trans/back/write.rs25
-rw-r--r--src/librustc_trans/base.rs10
-rw-r--r--src/librustc_trans/builder.rs4
-rw-r--r--src/librustc_trans/collector.rs14
-rw-r--r--src/librustc_trans/common.rs2
-rw-r--r--src/librustc_trans/context.rs88
-rw-r--r--src/librustc_trans/debuginfo/create_scope_map.rs2
-rw-r--r--src/librustc_trans/debuginfo/doc.rs8
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs46
-rw-r--r--src/librustc_trans/debuginfo/mod.rs8
-rw-r--r--src/librustc_trans/debuginfo/source_loc.rs6
-rw-r--r--src/librustc_trans/lib.rs23
-rw-r--r--src/librustc_trans/mir/block.rs8
-rw-r--r--src/librustc_trans/mir/constant.rs14
-rw-r--r--src/librustc_trans/mir/lvalue.rs2
-rw-r--r--src/librustc_trans/mir/mod.rs18
-rw-r--r--src/librustc_trans/mir/operand.rs6
-rw-r--r--src/librustc_trans/mir/rvalue.rs32
-rw-r--r--src/librustc_trans/monomorphize.rs6
-rw-r--r--src/librustc_trans/partitioning.rs6
-rw-r--r--src/librustc_trans/trans_item.rs6
-rw-r--r--src/librustc_trans/type_.rs32
-rw-r--r--src/librustc_trans_utils/lib.rs3
-rw-r--r--src/librustc_trans_utils/link.rs7
-rw-r--r--src/librustc_tsan/Cargo.toml1
-rw-r--r--src/librustc_tsan/lib.rs9
-rw-r--r--src/librustc_typeck/astconv.rs168
-rw-r--r--src/librustc_typeck/check/autoderef.rs2
-rw-r--r--src/librustc_typeck/check/cast.rs12
-rw-r--r--src/librustc_typeck/check/coercion.rs13
-rw-r--r--src/librustc_typeck/check/method/confirm.rs21
-rw-r--r--src/librustc_typeck/check/method/mod.rs12
-rw-r--r--src/librustc_typeck/check/method/probe.rs57
-rw-r--r--src/librustc_typeck/check/method/suggest.rs3
-rw-r--r--src/librustc_typeck/check/mod.rs55
-rw-r--r--src/librustc_typeck/check/regionck.rs17
-rw-r--r--src/librustc_typeck/check/wfcheck.rs15
-rw-r--r--src/librustc_typeck/check/writeback.rs8
-rw-r--r--src/librustc_typeck/check_unused.rs11
-rw-r--r--src/librustc_typeck/collect.rs38
-rw-r--r--src/librustc_typeck/constrained_type_params.rs2
-rw-r--r--src/librustc_typeck/diagnostics.rs55
-rw-r--r--src/librustc_typeck/lib.rs20
-rw-r--r--src/librustc_typeck/variance/constraints.rs12
-rw-r--r--src/librustc_typeck/variance/terms.rs4
-rw-r--r--src/librustdoc/clean/inline.rs26
-rw-r--r--src/librustdoc/clean/mod.rs121
-rw-r--r--src/librustdoc/core.rs10
-rw-r--r--src/librustdoc/fold.rs5
-rw-r--r--src/librustdoc/html/highlight.rs6
-rw-r--r--src/librustdoc/html/markdown.rs18
-rw-r--r--src/librustdoc/html/render.rs69
-rw-r--r--src/librustdoc/html/static/rustdoc.css8
-rw-r--r--src/librustdoc/html/static/styles/main.css6
-rw-r--r--src/librustdoc/html/toc.rs10
-rw-r--r--src/librustdoc/lib.rs5
-rw-r--r--src/librustdoc/plugins.rs2
-rw-r--r--src/librustdoc/test.rs24
-rw-r--r--src/librustdoc/visit_ast.rs50
-rw-r--r--src/librustdoc/visit_lib.rs2
-rw-r--r--src/libserialize/json.rs4
-rw-r--r--src/libserialize/lib.rs3
-rw-r--r--src/libserialize/opaque.rs4
-rw-r--r--src/libstd/build.rs4
-rw-r--r--src/libstd/collections/hash/map.rs18
-rw-r--r--src/libstd/collections/hash/set.rs4
-rw-r--r--src/libstd/collections/hash/table.rs14
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/ffi/os_str.rs2
-rw-r--r--src/libstd/fs.rs8
-rw-r--r--src/libstd/io/buffered.rs2
-rw-r--r--src/libstd/io/cursor.rs2
-rw-r--r--src/libstd/io/error.rs4
-rw-r--r--src/libstd/io/lazy.rs2
-rw-r--r--src/libstd/io/mod.rs110
-rw-r--r--src/libstd/lib.rs8
-rw-r--r--src/libstd/memchr.rs4
-rw-r--r--src/libstd/panicking.rs2
-rw-r--r--src/libstd/path.rs24
-rw-r--r--src/libstd/prelude/mod.rs1
-rw-r--r--src/libstd/primitive_docs.rs39
-rw-r--r--src/libstd/process.rs8
-rw-r--r--src/libstd/sync/mpsc/blocking.rs2
-rw-r--r--src/libstd/sync/mpsc/select.rs4
-rw-r--r--src/libstd/sync/mpsc/sync.rs2
-rw-r--r--src/libstd/sync/once.rs2
-rw-r--r--src/libstd/sys/redox/args.rs2
-rw-r--r--src/libstd/sys/redox/backtrace.rs32
-rw-r--r--src/libstd/sys/redox/backtrace/mod.rs42
-rw-r--r--src/libstd/sys/redox/backtrace/printing.rs11
-rw-r--r--src/libstd/sys/redox/backtrace/tracing.rs106
-rw-r--r--src/libstd/sys/redox/ext/mod.rs2
-rw-r--r--src/libstd/sys/redox/net/dns/mod.rs8
-rw-r--r--src/libstd/sys/redox/process.rs2
-rw-r--r--src/libstd/sys/unix/args.rs2
-rw-r--r--src/libstd/sys/unix/backtrace/tracing/gcc_s.rs2
-rw-r--r--src/libstd/sys/unix/ext/fs.rs2
-rw-r--r--src/libstd/sys/unix/ext/io.rs57
-rw-r--r--src/libstd/sys/unix/ext/mod.rs2
-rw-r--r--src/libstd/sys/unix/ext/net.rs68
-rw-r--r--src/libstd/sys/unix/fs.rs8
-rw-r--r--src/libstd/sys/unix/process/magenta.rs2
-rw-r--r--src/libstd/sys/unix/process/process_common.rs4
-rw-r--r--src/libstd/sys/unix/thread.rs3
-rw-r--r--src/libstd/sys/unix/weak.rs2
-rw-r--r--src/libstd/sys/windows/backtrace/mod.rs4
-rw-r--r--src/libstd/sys/windows/c.rs1
-rw-r--r--src/libstd/sys/windows/pipe.rs8
-rw-r--r--src/libstd/sys/windows/thread.rs6
-rw-r--r--src/libstd/sys/windows/thread_local.rs4
-rw-r--r--src/libstd/sys_common/thread_info.rs4
-rw-r--r--src/libstd/sys_common/thread_local.rs2
-rw-r--r--src/libstd/sys_common/wtf8.rs10
-rw-r--r--src/libstd/thread/local.rs4
-rw-r--r--src/libstd/thread/mod.rs11
-rw-r--r--src/libstd/time/duration.rs8
-rw-r--r--src/libstd/time/mod.rs2
-rw-r--r--src/libstd_unicode/lib.rs3
-rw-r--r--src/libstd_unicode/lossy.rs18
-rw-r--r--src/libstd_unicode/u_str.rs2
-rw-r--r--src/libsyntax/ast.rs38
-rw-r--r--src/libsyntax/attr.rs45
-rw-r--r--src/libsyntax/codemap.rs28
-rw-r--r--src/libsyntax/config.rs10
-rw-r--r--src/libsyntax/diagnostics/plugin.rs4
-rw-r--r--src/libsyntax/ext/base.rs6
-rw-r--r--src/libsyntax/ext/build.rs58
-rw-r--r--src/libsyntax/ext/expand.rs15
-rw-r--r--src/libsyntax/ext/placeholders.rs18
-rw-r--r--src/libsyntax/ext/quote.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs10
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs6
-rw-r--r--src/libsyntax/ext/tt/quoted.rs4
-rw-r--r--src/libsyntax/feature_gate.rs92
-rw-r--r--src/libsyntax/fold.rs30
-rw-r--r--src/libsyntax/json.rs16
-rw-r--r--src/libsyntax/lib.rs3
-rw-r--r--src/libsyntax/parse/attr.rs18
-rw-r--r--src/libsyntax/parse/lexer/comments.rs6
-rw-r--r--src/libsyntax/parse/lexer/mod.rs10
-rw-r--r--src/libsyntax/parse/lexer/tokentrees.rs2
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs227
-rw-r--r--src/libsyntax/print/pp.rs2
-rw-r--r--src/libsyntax/print/pprust.rs6
-rw-r--r--src/libsyntax/show_span.rs4
-rw-r--r--src/libsyntax/std_inject.rs6
-rw-r--r--src/libsyntax/test.rs39
-rw-r--r--src/libsyntax_ext/Cargo.toml1
-rw-r--r--src/libsyntax_ext/asm.rs16
-rw-r--r--src/libsyntax_ext/deriving/bounds.rs4
-rw-r--r--src/libsyntax_ext/deriving/clone.rs2
-rw-r--r--src/libsyntax_ext/deriving/cmp/eq.rs2
-rw-r--r--src/libsyntax_ext/deriving/cmp/ord.rs2
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_eq.rs4
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_ord.rs6
-rw-r--r--src/libsyntax_ext/deriving/debug.rs2
-rw-r--r--src/libsyntax_ext/deriving/decodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/default.rs2
-rw-r--r--src/libsyntax_ext/deriving/encodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs40
-rw-r--r--src/libsyntax_ext/deriving/generic/ty.rs16
-rw-r--r--src/libsyntax_ext/deriving/hash.rs4
-rw-r--r--src/libsyntax_ext/deriving/mod.rs2
-rw-r--r--src/libsyntax_ext/format.rs12
-rw-r--r--src/libsyntax_ext/format_foreign.rs18
-rw-r--r--src/libsyntax_ext/global_asm.rs2
-rw-r--r--src/libsyntax_ext/lib.rs4
-rw-r--r--src/libsyntax_ext/proc_macro_registrar.rs8
-rw-r--r--src/libsyntax_pos/hygiene.rs28
-rw-r--r--src/libsyntax_pos/lib.rs46
-rw-r--r--src/libterm/lib.rs3
-rw-r--r--src/libterm/terminfo/mod.rs2
-rw-r--r--src/libterm/terminfo/parser/compiled.rs4
-rw-r--r--src/libtest/lib.rs47
-rw-r--r--src/libunwind/build.rs4
-rw-r--r--src/libunwind/lib.rs8
-rw-r--r--src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs1
-rw-r--r--src/test/compile-fail/E0254.rs1
-rw-r--r--src/test/compile-fail/E0259.rs1
-rw-r--r--src/test/compile-fail/E0260.rs1
-rw-r--r--src/test/compile-fail/associated-types-eq-expr-path.rs2
-rw-r--r--src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs9
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs4
-rw-r--r--src/test/compile-fail/enable-unstable-lib-feature.rs1
-rw-r--r--src/test/compile-fail/feature-gate-fn_must_use.rs31
-rw-r--r--src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs1
-rw-r--r--src/test/compile-fail/foreign-fn-return-lifetime.rs16
-rw-r--r--src/test/compile-fail/issue-11493.rs4
-rw-r--r--src/test/compile-fail/issue-12567.rs8
-rw-r--r--src/test/compile-fail/issue-17545.rs4
-rw-r--r--src/test/compile-fail/issue-17718-constants-not-static.rs4
-rw-r--r--src/test/compile-fail/issue-27592.rs4
-rw-r--r--src/test/compile-fail/issue-32995.rs8
-rw-r--r--src/test/compile-fail/issue-36116.rs28
-rw-r--r--src/test/compile-fail/issue-36881.rs1
-rw-r--r--src/test/compile-fail/issue-43424.rs22
-rw-r--r--src/test/compile-fail/issue-43431.rs24
-rw-r--r--src/test/compile-fail/issue-43784-associated-type.rs25
-rw-r--r--src/test/compile-fail/issue-43784-supertrait.rs18
-rw-r--r--src/test/compile-fail/lint-stability-deprecated.rs2
-rw-r--r--src/test/compile-fail/lint-unused-extern-crate.rs5
-rw-r--r--src/test/compile-fail/macro-reexport-malformed-1.rs1
-rw-r--r--src/test/compile-fail/macro-reexport-malformed-2.rs1
-rw-r--r--src/test/compile-fail/macro-reexport-malformed-3.rs1
-rw-r--r--src/test/compile-fail/macro-use-bad-args-1.rs1
-rw-r--r--src/test/compile-fail/macro-use-bad-args-2.rs1
-rw-r--r--src/test/compile-fail/method-call-type-binding.rs2
-rw-r--r--src/test/compile-fail/move-out-of-array-1.rs2
-rw-r--r--src/test/compile-fail/move-out-of-slice-1.rs2
-rw-r--r--src/test/compile-fail/no-std-inject.rs1
-rw-r--r--src/test/compile-fail/placement-expr-unstable.rs2
-rw-r--r--src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs8
-rw-r--r--src/test/compile-fail/regions-ret.rs4
-rw-r--r--src/test/compile-fail/regions-var-type-out-of-scope.rs4
-rw-r--r--src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs1
-rw-r--r--src/test/compile-fail/resolve_self_super_hint.rs1
-rw-r--r--src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs16
-rw-r--r--src/test/compile-fail/static-reference-to-fn-2.rs11
-rw-r--r--src/test/compile-fail/static-region-bound.rs4
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs (renamed from src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs)12
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs1
-rw-r--r--src/test/compile-fail/unused-attr.rs2
-rw-r--r--src/test/mir-opt/issue-43457.rs55
-rw-r--r--src/test/parse-fail/type-parameters-in-field-exprs.rs2
-rw-r--r--src/test/run-make/alloc-extern-crates/Makefile2
-rw-r--r--src/test/run-pass-fulldeps/issue-13560.rs1
-rw-r--r--src/test/run-pass-fulldeps/linkage-visibility.rs1
-rw-r--r--src/test/run-pass/builtin-clone-unwind.rs65
-rw-r--r--src/test/run-pass/builtin-clone.rs54
-rw-r--r--src/test/run-pass/deprecation-in-force-unstable.rs14
-rw-r--r--src/test/run-pass/issue-37725.rs8
-rw-r--r--src/test/run-pass/issue-43205.rs (renamed from src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs)5
-rw-r--r--src/test/run-pass/issue-43910.rs (renamed from src/test/compile-fail/feature-gate-rvalue_static_promotion.rs)7
-rw-r--r--src/test/run-pass/issue-43923.rs19
-rw-r--r--src/test/run-pass/lint-unknown-lints-at-crate-level.rs16
-rw-r--r--src/test/run-pass/rvalue-static-promotion.rs2
-rw-r--r--src/test/run-pass/union/union-basic.rs8
-rw-r--r--src/test/run-pass/wrong-hashset-issue-42918.rs38
-rw-r--r--src/test/rustdoc/issue-43869.rs32
-rw-r--r--src/test/rustdoc/remove-duplicates.rs24
-rw-r--r--src/test/ui/issue-13483.rs25
-rw-r--r--src/test/ui/issue-13483.stderr14
-rw-r--r--src/test/ui/issue-41652/issue_41652.stderr1
-rw-r--r--src/test/ui/issue-44023.rs16
-rw-r--r--src/test/ui/issue-44023.stderr13
-rw-r--r--src/test/ui/issue-44078.rs13
-rw-r--r--src/test/ui/issue-44078.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr23
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs5
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr20
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr20
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs19
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr12
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs18
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr12
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs17
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs20
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs22
-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.rs22
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr23
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs18
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions.rs2
-rw-r--r--src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr2
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.rs2
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.stderr7
-rw-r--r--src/test/ui/lint/fn_must_use.rs1
-rw-r--r--src/test/ui/lint/fn_must_use.stderr12
-rw-r--r--src/test/ui/resolve/enums-are-namespaced-xc.stderr6
-rw-r--r--src/test/ui/resolve/issue-21221-3.stderr2
-rw-r--r--src/test/ui/resolve/issue-21221-4.stderr2
-rw-r--r--src/test/ui/resolve/issue-3907.stderr2
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr6
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.rs27
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.stderr38
-rw-r--r--src/test/ui/span/E0536.stderr2
-rw-r--r--src/test/ui/span/E0537.stderr2
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.rs8
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.stderr30
-rw-r--r--src/test/ui/span/import-ty-params.rs4
-rw-r--r--src/test/ui/span/import-ty-params.stderr16
-rw-r--r--src/test/ui/span/issue-15480.rs4
-rw-r--r--src/test/ui/span/issue-15480.stderr10
-rw-r--r--src/test/ui/span/issue-24690.stderr1
-rw-r--r--src/test/ui/span/issue-7575.stderr3
-rw-r--r--src/test/ui/span/macro-ty-params.rs10
-rw-r--r--src/test/ui/span/macro-ty-params.stderr22
-rw-r--r--src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs4
-rw-r--r--src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr12
-rw-r--r--src/test/ui/span/slice-borrow.rs2
-rw-r--r--src/test/ui/span/slice-borrow.stderr6
-rw-r--r--src/test/ui/span/visibility-ty-params.rs4
-rw-r--r--src/test/ui/span/visibility-ty-params.stderr24
-rw-r--r--src/test/ui/union-sized-field.rs26
-rw-r--r--src/test/ui/union-sized-field.stderr32
-rw-r--r--src/tools/build-manifest/src/main.rs15
m---------src/tools/cargo0
-rw-r--r--src/tools/compiletest/src/errors.rs6
-rw-r--r--src/tools/compiletest/src/json.rs4
-rw-r--r--src/tools/compiletest/src/main.rs14
-rw-r--r--src/tools/compiletest/src/procsrv.rs134
-rw-r--r--src/tools/compiletest/src/runtest.rs576
m---------src/tools/rls0
674 files changed, 11848 insertions, 7829 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9c54dfd3388..c424ca7ab00 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -415,4 +415,4 @@ are:
 [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
 [rctd]: ./src/test/COMPILER_TESTS.md
-[cheatsheet]: https://buildbot.rust-lang.org/homu/
+[cheatsheet]: https://buildbot2.rust-lang.org/homu/
diff --git a/README.md b/README.md
index b6ff6df0aec..78a9f509bbc 100644
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ Windows build triples are:
     - `i686-pc-windows-msvc`
     - `x86_64-pc-windows-msvc`
 
-The build triple can be specified by either specifying `--build=ABI` when
+The build triple can be specified by either specifying `--build=<triple>` when
 invoking `x.py` commands, or by copying the `config.toml` file (as described
 in Building From Source), and modifying the `build` option under the `[build]`
 section.
diff --git a/RELEASES.md b/RELEASES.md
index 7bf0bcab640..c3a7367a2ee 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -92,7 +92,7 @@ Stabilized APIs
 Cargo
 -----
 - [Cargo API token location moved from `~/.cargo/config` to
-  `~/cargo/credentials`.][cargo/3978]
+  `~/.cargo/credentials`.][cargo/3978]
 - [Cargo will now build `main.rs` binaries that are in sub-directories of
   `src/bin`.][cargo/4214] ie. Having `src/bin/server/main.rs` and
   `src/bin/client/main.rs` generates `target/debug/server` and `target/debug/client`
@@ -172,7 +172,6 @@ Compatibility Notes
 [`slice::sort_unstable`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable
 [`ste::from_boxed_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html
 [`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut
-[`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut
 [`str::from_utf8_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_mut.html
 [`str::from_utf8_unchecked_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked_mut.html
 [`str::get_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.get_mut
@@ -898,6 +897,9 @@ Compatibility Notes
 * [Ctrl-Z returns from `Stdin.read()` when reading from the console on
   Windows][38274]
 * [Clean up semantics of `self` in an import list][38313]
+* Reimplemented lifetime elision. This change was almost entirely compatible
+  with existing code, but it did close a number of small bugs and loopholes,
+  as well as being more accepting in some other [cases][41105].
 
 [37057]: https://github.com/rust-lang/rust/pull/37057
 [37761]: https://github.com/rust-lang/rust/pull/37761
@@ -932,6 +934,7 @@ Compatibility Notes
 [39048]: https://github.com/rust-lang/rust/pull/39048
 [39282]: https://github.com/rust-lang/rust/pull/39282
 [39379]: https://github.com/rust-lang/rust/pull/39379
+[41105]: https://github.com/rust-lang/rust/issues/41105
 [`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
 [`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
 [`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add
diff --git a/appveyor.yml b/appveyor.yml
index aaede7236a9..f548d6694c8 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -16,7 +16,7 @@ environment:
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
     SCRIPT: python x.py test
   - MSYS_BITS: 32
-    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc
+    RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i686-pc-windows-msvc
     SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc
 
   # MSVC aux tests
@@ -145,7 +145,8 @@ install:
   # - set PATH=%PATH%;%CD% -- this already happens above for sccache
 
   # Install InnoSetup to get `iscc` used to produce installers
-  - appveyor-retry choco install -y InnoSetup
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-08-22-is.exe
+  - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
   - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
 
   # Help debug some handle issues on AppVeyor
diff --git a/config.toml.example b/config.toml.example
index 48d27fa58ca..3f5101ebf34 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -73,6 +73,10 @@
 # controlled by rustbuild's -j parameter.
 #link-jobs = 0
 
+# When invoking `llvm-config` this configures whether the `--shared` argument is
+# passed to prefer linking to shared libraries.
+#link-shared = false
+
 # =============================================================================
 # General build configuration options
 # =============================================================================
@@ -166,6 +170,15 @@
 # to +10 on Unix platforms, and by using a "low priority" job object on Windows.
 #low-priority = false
 
+# Arguments passed to the `./configure` script, used during distcheck. You
+# probably won't fill this in but rather it's filled in by the `./configure`
+# script.
+#configure-args = []
+
+# Indicates that a local rebuild is ocurring instead of a full bootstrap,
+# essentially skipping stage0 as the local compiler is recompiling itself again.
+#local-rebuild = false
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
@@ -195,6 +208,13 @@
 # =============================================================================
 [rust]
 
+# Indicates that the build should be optimized for debugging Rust. Note that
+# this is typically not what you want as it takes an incredibly large amount of
+# time to have a debug-mode rustc compile any code (notably libstd). If this
+# value is set to `true` it will affect a number of configuration options below
+# as well, if unconfigured.
+#debug = false
+
 # Whether or not to optimize the compiler and standard library
 # Note: the slowness of the non optimized compiler compiling itself usually
 #       outweighs the time gains in not doing optimizations, therefore a
@@ -249,6 +269,10 @@
 # desired in distributions, for example.
 #rpath = true
 
+# Suppresses extraneous output from tests to ensure the output of the test
+# harness is relatively clean.
+#quiet-tests = false
+
 # Flag indicating whether tests are compiled with optimizations (the -O flag) or
 # with debuginfo (the -g flag)
 #optimize-tests = true
@@ -264,6 +288,9 @@
 # will default to true if channel = "dev", but will default to false otherwise.
 #ignore-git = true
 
+# When creating source tarballs whether or not to create a source tarball.
+#dist-src = false
+
 # =============================================================================
 # Options for specific targets
 #
@@ -295,12 +322,22 @@
 # build native code.
 #android-ndk = "/path/to/ndk"
 
+# Force static or dynamic linkage of the standard library for this target. If
+# this target is a host for rustc, this will also affect the linkage of the
+# compiler itself. This is useful for building rustc on targets that normally
+# only use static libraries. If unset, the target's default linkage is used.
+#crt-static = false
+
 # The root location of the MUSL installation directory. The library directory
 # will also need to contain libunwind.a for an unwinding implementation. Note
 # that this option only makes sense for MUSL targets that produce statically
 # linked binaries
 #musl-root = "..."
 
+# Used in testing for configuring where the QEMU images are located, you
+# probably don't want to use this.
+#qemu-rootfs = "..."
+
 # =============================================================================
 # Distribution options
 #
diff --git a/configure b/configure
index 664b473b2c9..eeb8d081d34 100755
--- a/configure
+++ b/configure
@@ -1,779 +1,17 @@
 #!/bin/sh
 
-# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/bash is.
-if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
-    POSIX_SHELL="true"
-    export POSIX_SHELL
-    exec /usr/bin/env bash $0 "$@"
-fi
-unset POSIX_SHELL # clear it so if we invoke other scripts, they run as bash as well
+script="$(dirname $0)"/src/bootstrap/configure.py
 
-msg() {
-    echo "configure: $*"
-}
-
-step_msg() {
-    msg
-    msg "$1"
-    msg
-}
-
-warn() {
-    echo "configure: WARNING: $1"
-}
-
-err() {
-    echo "configure: error: $1"
-    exit 1
-}
-
-run() {
-    msg "$@"
-    "$@"
-}
-
-need_ok() {
-    if [ $? -ne 0 ]
-    then
-        err "$1"
-    fi
-}
-
-need_cmd() {
-    if command -v $1 >/dev/null 2>&1
-    then msg "found program '$1'"
-    else err "program '$1' is missing, please install it"
-    fi
-}
-
-make_dir() {
-    if [ ! -d $1 ]
-    then
-        run mkdir -p $1
-    fi
-}
-
-copy_if_changed() {
-    if cmp -s $1 $2
-    then
-        msg "leaving $2 unchanged"
-    else
-        run cp -f $1 $2
-        chmod u-w $2 # make copied artifact read-only
-    fi
-}
-
-move_if_changed() {
-    if cmp -s $1 $2
-    then
-        msg "leaving $2 unchanged"
-    else
-        run mv -f $1 $2
-        chmod u-w $2 # make moved artifact read-only
-    fi
-}
-
-putvar() {
-    local T
-    eval T=\$$1
-    eval TLEN=\${#$1}
-    if [ $TLEN -gt 35 ]
-    then
-        printf "configure: %-20s := %.35s ...\n" $1 "$T"
-    else
-        printf "configure: %-20s := %s %s\n" $1 "$T" "$2"
-    fi
-    printf "%-20s := %s\n" $1 "$T" >>config.tmp
-}
-
-putpathvar() {
-    local T
-    eval T=\$$1
-    eval TLEN=\${#$1}
-    if [ $TLEN -gt 35 ]
-    then
-        printf "configure: %-20s := %.35s ...\n" $1 "$T"
-    else
-        printf "configure: %-20s := %s %s\n" $1 "$T" "$2"
-    fi
-    if [ -z "$T" ]
-    then
-        printf "%-20s := \n" $1 >>config.tmp
-    else
-        printf "%-20s := \"%s\"\n" $1 "$T" >>config.tmp
-    fi
-}
-
-probe() {
-    local V=$1
+try() {
+    cmd=$1
     shift
-    local P
-    local T
-    for P
-    do
-        T=$(command -v $P 2>&1)
-        if [ $? -eq 0 ]
-        then
-            VER0=$($P --version 2>/dev/null \
-                |  grep -o '[vV]\?[0-9][0-9.][a-z0-9.-]*' | head -1 )
-            if [ $? -eq 0 -a "x${VER0}" != "x" ]
-            then
-              VER="($VER0)"
-            else
-              VER=""
-            fi
-            break
-        else
-            VER=""
-            T=""
-        fi
-    done
-    eval $V=\$T
-    putpathvar $V "$VER"
-}
-
-probe_need() {
-    probe $*
-    local V=$1
-    shift
-    eval VV=\$$V
-    if [ -z "$VV" ]
-    then
-        err "$V needed, but unable to find any of: $*"
-    fi
-}
-
-validate_opt () {
-    for arg in $CFG_CONFIGURE_ARGS
-    do
-        isArgValid=0
-        for option in $BOOL_OPTIONS
-        do
-            if test --disable-$option = $arg
-            then
-                isArgValid=1
-            fi
-            if test --enable-$option = $arg
-            then
-                isArgValid=1
-            fi
-        done
-        for option in $VAL_OPTIONS
-        do
-            if echo "$arg" | grep -q -- "--$option="
-            then
-                isArgValid=1
-            fi
-        done
-        if [ "$arg" = "--help" ]
-        then
-            echo
-            echo "No more help available for Configure options,"
-            echo "check the Wiki or join our IRC channel"
-            break
-        else
-            if test $isArgValid -eq 0
-            then
-                err "Option '$arg' is not recognized"
-            fi
-        fi
-    done
-}
-
-# `valopt OPTION_NAME DEFAULT DOC` extracts a string-valued option
-# from command line, using provided default value for the option if
-# not present, and saves it to the generated config.mk.
-#
-# `valopt_nosave` is much the same, except that it does not save the
-# result to config.mk (instead the script should use `putvar` itself
-# later on to save it).  `valopt_core` is the core upon which the
-# other two are built.
-
-valopt_core() {
-    VAL_OPTIONS="$VAL_OPTIONS $2"
-
-    local SAVE=$1
-    local OP=$2
-    local DEFAULT=$3
-    shift
-    shift
-    shift
-    local DOC="$*"
-    if [ $HELP -eq 0 ]
-    then
-        local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
-        local V="CFG_${UOP}"
-        local V_PROVIDED="${V}_PROVIDED"
-        eval $V="$DEFAULT"
-        for arg in $CFG_CONFIGURE_ARGS
-        do
-            if echo "$arg" | grep -q -- "--$OP="
-            then
-                val=$(echo "$arg" | cut -f2 -d=)
-                eval $V=$val
-                eval $V_PROVIDED=1
-            fi
-        done
-        if [ "$SAVE" = "save" ]
-        then
-            putvar $V
-        fi
-    else
-        if [ -z "$DEFAULT" ]
-        then
-            DEFAULT="<none>"
-        fi
-        OP="${OP}=[${DEFAULT}]"
-        printf "    --%-30s %s\n" "$OP" "$DOC"
-    fi
-}
-
-valopt_nosave() {
-    valopt_core nosave "$@"
-}
-
-valopt() {
-    valopt_core save "$@"
-}
-
-# `opt OPTION_NAME DEFAULT DOC` extracts a boolean-valued option from
-# command line, using the provided default value (0/1) for the option
-# if not present, and saves it to the generated config.mk.
-#
-# `opt_nosave` is much the same, except that it does not save the
-# result to config.mk (instead the script should use `putvar` itself
-# later on to save it).  `opt_core` is the core upon which the other
-# two are built.
-
-opt_core() {
-    BOOL_OPTIONS="$BOOL_OPTIONS $2"
-
-    local SAVE=$1
-    local OP=$2
-    local DEFAULT=$3
-    shift
-    shift
-    shift
-    local DOC="$*"
-    local FLAG=""
-
-    if [ $DEFAULT -eq 0 ]
-    then
-        FLAG="enable"
-        DEFAULT_FLAG="disable"
-    else
-        FLAG="disable"
-        DEFAULT_FLAG="enable"
-        DOC="don't $DOC"
-    fi
-
-    if [ $HELP -eq 0 ]
-    then
-        for arg in $CFG_CONFIGURE_ARGS
-        do
-            if [ "$arg" = "--${FLAG}-${OP}" ]
-            then
-                OP=$(echo $OP | tr 'a-z-' 'A-Z_')
-                FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
-                local V="CFG_${FLAG}_${OP}"
-                local V_PROVIDED="CFG_${FLAG}_${OP}_PROVIDED"
-                eval $V=1
-                eval $V_PROVIDED=1
-                if [ "$SAVE" = "save" ]
-                then
-                   putvar $V
-                fi
-            elif [ "$arg" = "--${DEFAULT_FLAG}-${OP}" ]
-            then
-                OP=$(echo $OP | tr 'a-z-' 'A-Z_')
-                DEFAULT_FLAG=$(echo $DEFAULT_FLAG | tr 'a-z' 'A-Z')
-                local V_PROVIDED="CFG_${DEFAULT_FLAG}_${OP}_PROVIDED"
-                eval $V_PROVIDED=1
-            fi
-        done
-    else
-        if [ -n "$META" ]
-        then
-            OP="$OP=<$META>"
-        fi
-        printf "    --%-30s %s\n" "$FLAG-$OP" "$DOC"
-     fi
-}
-
-opt_nosave() {
-    opt_core nosave "$@"
-}
-
-opt() {
-    opt_core save "$@"
-}
-
-envopt() {
-    local NAME=$1
-    local V="CFG_${NAME}"
-    eval VV=\$$V
-
-    # If configure didn't set a value already, then check environment.
-    #
-    # (It is recommended that the configure script always check the
-    # environment before setting any values to envopt variables; see
-    # e.g.  how CFG_CC is handled, where it first checks `-z "$CC"`,
-    # and issues msg if it ends up employing that provided value.)
-    if [ -z "$VV" ]
-    then
-        eval $V=\$$NAME
-        eval VV=\$$V
-    fi
-
-    # If script or environment provided a value, save it.
-    if [ -n "$VV" ]
-    then
-        putvar $V
-    fi
-}
-
-enable_if_not_disabled() {
-    local OP=$1
-    local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
-    local ENAB_V="CFG_ENABLE_$UOP"
-    local EXPLICITLY_DISABLED="CFG_DISABLE_${UOP}_PROVIDED"
-    eval VV=\$$EXPLICITLY_DISABLED
-    if [ -z "$VV" ]; then
-        eval $ENAB_V=1
+    T=$($cmd --version 2>/dev/null)
+    if [ $? -eq 0 ]; then
+        exec $cmd "$script" "$@"
     fi
 }
 
-to_gnu_triple() {
-    case $1 in
-        i686-pc-windows-gnu) echo i686-w64-mingw32 ;;
-        x86_64-pc-windows-gnu) echo x86_64-w64-mingw32 ;;
-        *) echo $1 ;;
-    esac
-}
-
-# Prints the absolute path of a directory to stdout
-abs_path() {
-    local _path="$1"
-    # Unset CDPATH because it causes havok: it makes the destination unpredictable
-    # and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null
-    # for good measure.
-    (unset CDPATH && cd "$_path" > /dev/null && pwd)
-}
-
-HELP=0
-for arg; do
-    case "$arg" in
-        --help) HELP=1;;
-    esac
-done
-
-msg "looking for configure programs"
-need_cmd cmp
-need_cmd mkdir
-need_cmd printf
-need_cmd cut
-need_cmd head
-need_cmd grep
-need_cmd xargs
-need_cmd cp
-need_cmd find
-need_cmd uname
-need_cmd date
-need_cmd tr
-need_cmd sed
-need_cmd file
-need_cmd make
-
-CFG_SRC_DIR="$(abs_path $(dirname $0))/"
-CFG_SRC_DIR_RELATIVE="$(dirname $0)/"
-CFG_BUILD_DIR="$(pwd)/"
-CFG_SELF="$0"
-CFG_CONFIGURE_ARGS="$@"
-
-
-case "${CFG_SRC_DIR}" in
-    *\ * )
-        err "The path to the rust source directory contains spaces, which is not supported"
-        ;;
-    *)
-        ;;
-esac
-
-
-OPTIONS=""
-if [ "$HELP" -eq 1 ]
-then
-    echo
-    echo "Usage: $CFG_SELF [options]"
-    echo
-    echo "Options:"
-    echo
-else
-    msg "recreating config.tmp"
-    echo '' >config.tmp
-
-    step_msg "processing $CFG_SELF args"
-fi
-
-BOOL_OPTIONS=""
-VAL_OPTIONS=""
-
-opt debug 0 "debug mode; disables optimization unless \`--enable-optimize\` given"
-opt valgrind 0 "run tests with valgrind (memcheck by default)"
-opt helgrind 0 "run tests with helgrind instead of memcheck"
-opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind"
-opt docs     1 "build standard library documentation"
-opt compiler-docs     0 "build compiler documentation"
-opt optimize-tests 1 "build tests with optimizations"
-opt debuginfo-tests 0 "build tests with debugger metadata"
-opt quiet-tests 0 "enable quieter output when running tests"
-opt libcpp 1 "build llvm with libc++ instead of libstdc++ when using clang"
-opt llvm-assertions 0 "build LLVM with assertions"
-opt debug-assertions 0 "build with debugging assertions"
-opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
-opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
-opt sccache 0 "invoke gcc/clang via sccache to reuse object files between builds"
-opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
-opt local-rebuild 0 "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version"
-opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
-opt llvm-link-shared 0 "prefer shared linking to LLVM (llvm-config --link-shared)"
-opt rpath 1 "build rpaths into rustc itself"
-opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
-# This is used by the automation to produce single-target nightlies
-opt dist-host-only 0 "only install bins for the host architecture"
-opt inject-std-version 1 "inject the current compiler version of libstd into programs"
-opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
-opt codegen-tests 1 "run the src/test/codegen tests"
-opt option-checking 1 "complain about unrecognized options in this configure script"
-opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
-opt locked-deps 0 "force Cargo.lock to be up to date"
-opt vendor 0 "enable usage of vendored Rust crates"
-opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)"
-opt dist-src 1 "when building tarballs enables building a source tarball"
-opt cargo-openssl-static 0 "static openssl in cargo"
-opt profiler 0 "build the profiler runtime"
-
-# Optimization and debugging options. These may be overridden by the release channel, etc.
-opt_nosave optimize 1 "build optimized rust code"
-opt_nosave optimize-cxx 1 "build optimized C++ code"
-opt_nosave optimize-llvm 1 "build optimized LLVM"
-opt_nosave llvm-assertions 0 "build LLVM with assertions"
-opt_nosave debug-assertions 0 "build with debugging assertions"
-opt_nosave llvm-release-debuginfo 0 "build LLVM with debugger metadata"
-opt_nosave debuginfo 0 "build with debugger metadata"
-opt_nosave debuginfo-lines 0 "build with line number debugger metadata"
-opt_nosave debuginfo-only-std 0 "build only libstd with debugging information"
-opt_nosave debug-jemalloc 0 "build jemalloc with --enable-debug --enable-fill"
-
-valopt localstatedir "/var/lib" "local state directory"
-valopt sysconfdir "/etc" "install system configuration files"
-
-valopt datadir "${CFG_PREFIX}/share" "install data"
-valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
-valopt llvm-root "" "set LLVM root"
-valopt python "" "set path to python"
-valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
-valopt build "" "GNUs ./configure syntax LLVM build triple"
-valopt android-cross-path "" "Android NDK standalone path (deprecated)"
-valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
-valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
-valopt armv7-linux-androideabi-ndk "" "armv7-linux-androideabi NDK standalone path"
-valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path"
-valopt x86_64-linux-android-ndk "" "x86_64-linux-android NDK standalone path"
-valopt nacl-cross-path  "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!"
-valopt musl-root "/usr/local" "MUSL root installation directory (deprecated)"
-valopt musl-root-x86_64 "" "x86_64-unknown-linux-musl install directory"
-valopt musl-root-i686 "" "i686-unknown-linux-musl install directory"
-valopt musl-root-arm "" "arm-unknown-linux-musleabi install directory"
-valopt musl-root-armhf "" "arm-unknown-linux-musleabihf install directory"
-valopt musl-root-armv7 "" "armv7-unknown-linux-musleabihf install directory"
-valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag"
-valopt qemu-armhf-rootfs "" "rootfs in qemu testing, you probably don't want to use this"
-valopt qemu-aarch64-rootfs "" "rootfs in qemu testing, you probably don't want to use this"
-valopt experimental-targets "" "experimental LLVM targets to build"
-
-if [ -e ${CFG_SRC_DIR}.git ]
-then
-    valopt release-channel "dev" "the name of the release channel to build"
-else
-    # If we have no git directory then we are probably a tarball distribution
-    # and should default to stable channel - Issue 28322
-    probe CFG_GIT          git
-    msg "git: no git directory. Changing default release channel to stable"
-    valopt release-channel "stable" "the name of the release channel to build"
-fi
-
-# Used on systems where "cc" and "ar" are unavailable
-valopt default-linker "cc" "the default linker"
-valopt default-ar     "ar" "the default ar"
-
-# Many of these are saved below during the "writing configuration" step
-# (others are conditionally saved).
-opt_nosave manage-submodules 1 "let the build manage the git submodules"
-opt_nosave clang 0 "prefer clang to gcc for building the runtime"
-opt_nosave jemalloc 1 "build liballoc with jemalloc"
-opt full-bootstrap 0 "build three compilers instead of two"
-opt extended 0 "build an extended rust tool set"
-
-valopt_nosave prefix "/usr/local" "set installation prefix"
-valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
-valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
-valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
-valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
-valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install documentation in PATH"
-valopt_nosave bindir "${CFG_PREFIX}/bin" "install binaries"
-
-# On Windows this determines root of the subtree for target libraries.
-# Host runtime libs always go to 'bin'.
-valopt libdir "${CFG_PREFIX}/lib" "install libraries"
-
-case "$CFG_LIBDIR" in
-    "$CFG_PREFIX"/*) CAT_INC=2;;
-    "$CFG_PREFIX"*)  CAT_INC=1;;
-    *)
-        err "libdir must begin with the prefix. Use --prefix to set it accordingly.";;
-esac
-
-CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-`
-
-if [ $HELP -eq 1 ]
-then
-    echo
-    exit 0
-fi
-
-# Validate Options
-if [ -z "$CFG_DISABLE_OPTION_CHECKING" ]
-then
-    step_msg "validating $CFG_SELF args"
-    validate_opt
-fi
-
-# Validate the release channel, and configure options
-case "$CFG_RELEASE_CHANNEL" in
-    nightly )
-	msg "overriding settings for $CFG_RELEASE_CHANNEL"
-        enable_if_not_disabled llvm-assertions
-        # FIXME(stage0) re-enable this on the next stage0 now that #35566 is
-        # fixed
-        case "$CFG_BUILD" in
-          *-pc-windows-gnu)
-            ;;
-          *)
-            enable_if_not_disabled debuginfo-lines
-            enable_if_not_disabled debuginfo-only-std
-            ;;
-        esac
-
-	;;
-    beta | stable)
-	msg "overriding settings for $CFG_RELEASE_CHANNEL"
-        case "$CFG_BUILD" in
-          *-pc-windows-gnu)
-            ;;
-          *)
-            enable_if_not_disabled debuginfo-lines
-            enable_if_not_disabled debuginfo-only-std
-            ;;
-        esac
-	;;
-    dev)
-	;;
-    *)
-        err "release channel must be 'dev', 'nightly', 'beta' or 'stable'"
-        ;;
-esac
-
-# Adjust perf and debug options for debug mode
-if [ -n "$CFG_ENABLE_DEBUG" ]; then
-    msg "debug mode enabled, setting performance options"
-    if [ -z "$CFG_ENABLE_OPTIMIZE_PROVIDED" ]; then
-        msg "optimization not explicitly enabled, disabling optimization"
-        CFG_DISABLE_OPTIMIZE=1
-        CFG_DISABLE_OPTIMIZE_CXX=1
-    fi
-
-    # Set following variables to 1 unless setting already provided
-    enable_if_not_disabled debug-assertions
-    enable_if_not_disabled debug-jemalloc
-    enable_if_not_disabled debuginfo
-    enable_if_not_disabled llvm-assertions
-fi
-
-# OK, now write the debugging options
-if [ -n "$CFG_DISABLE_OPTIMIZE" ]; then putvar CFG_DISABLE_OPTIMIZE; fi
-if [ -n "$CFG_DISABLE_OPTIMIZE_CXX" ]; then putvar CFG_DISABLE_OPTIMIZE_CXX; fi
-if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then putvar CFG_DISABLE_OPTIMIZE_LLVM; fi
-if [ -n "$CFG_ENABLE_LLVM_ASSERTIONS" ]; then putvar CFG_ENABLE_LLVM_ASSERTIONS; fi
-if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTIONS; fi
-if [ -n "$CFG_ENABLE_LLVM_RELEASE_DEBUGINFO" ]; then putvar CFG_ENABLE_LLVM_RELEASE_DEBUGINFO; fi
-if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
-if [ -n "$CFG_ENABLE_DEBUGINFO_LINES" ]; then putvar CFG_ENABLE_DEBUGINFO_LINES; fi
-if [ -n "$CFG_ENABLE_DEBUGINFO_ONLY_STD" ]; then putvar CFG_ENABLE_DEBUGINFO_ONLY_STD; fi
-if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
-
-step_msg "looking for build programs"
-
-probe_need CFG_CURL curl
-if [ -z "$CFG_PYTHON_PROVIDED" ]; then
-    probe_need CFG_PYTHON      python2.7 python2 python
-fi
-
-python_version=$($CFG_PYTHON -V 2>&1)
-if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then
-    err "Found $python_version, but Python 2.7 is required"
-fi
-
-# the valgrind rpass tests will fail if you don't have a valgrind, but they're
-# only disabled if you opt out.
-if [ -z "$CFG_VALGRIND" ]
-then
-    # If the user has explicitly asked for valgrind tests, then fail
-    if [ -n "$CFG_ENABLE_VALGRIND" ] && [ -n "$CFG_ENABLE_VALGRIND_PROVIDED" ]
-    then
-        err "No valgrind present, but valgrind tests explicitly requested"
-    else
-        CFG_DISABLE_VALGRIND_RPASS=1
-        putvar CFG_DISABLE_VALGRIND_RPASS
-    fi
-fi
-
-# Do some sanity checks if running on buildbot
-# (these env vars are set by rust-buildbot)
-if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then
-   # Frequently the llvm submodule directory is broken by the build
-   # being killed
-   llvm_lock="${CFG_SRC_DIR}/.git/modules/src/llvm/index.lock"
-   if [ -e "$llvm_lock" ]; then
-       step_msg "removing $llvm_lock"
-       rm -f "$llvm_lock"
-   fi
-fi
-
-BIN_SUF=
-if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
-then
-    BIN_SUF=.exe
-fi
-
-# --enable-local-rebuild implies --enable-local-rust too
-if [ -n "$CFG_ENABLE_LOCAL_REBUILD" ]
-then
-    if [ -z "$CFG_ENABLE_LOCAL_RUST" ]
-    then
-        CFG_ENABLE_LOCAL_RUST=1
-        putvar CFG_ENABLE_LOCAL_RUST
-    fi
-fi
-
-if [ -n "$CFG_ENABLE_LOCAL_RUST" ]
-then
-    system_rustc=$(which rustc)
-    if [ -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} ]
-    then
-        : # everything already configured
-    elif [ -n "$system_rustc" ]
-    then
-        # we assume that rustc is in a /bin directory
-        CFG_LOCAL_RUST_ROOT=${system_rustc%/bin/rustc}
-    else
-        err "no local rust to use"
-    fi
-
-    CMD="${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF}"
-    LRV=`LD_LIBRARY_PATH=${CFG_LOCAL_RUST_ROOT}/lib $CMD --version`
-    if [ $? -ne 0 ]
-    then
-        step_msg "failure while running $CMD --version"
-        exit 1
-    fi
-    step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV"
-    putvar CFG_LOCAL_RUST_ROOT
-fi
-
-# Same with jemalloc.  save the setting here.
-if [ -n "$CFG_DISABLE_JEMALLOC" ]
-then
-    putvar CFG_DISABLE_JEMALLOC
-fi
-
-# All safeguards based on $CFG_ENABLE_CLANG should occur before this
-# point in the script; after this point, script logic should inspect
-# $CFG_USING_CLANG rather than $CFG_ENABLE_CLANG.
-
-# Set CFG_{CC,CXX,CPP,CFLAGS,CXXFLAGS,LDFLAGS}
-envopt CC
-envopt CXX
-envopt CPP
-envopt CFLAGS
-envopt CXXFLAGS
-envopt LDFLAGS
-
-# a little post-processing of various config values
-CFG_PREFIX=${CFG_PREFIX%/}
-CFG_MANDIR=${CFG_MANDIR%/}
-CFG_DOCDIR=${CFG_DOCDIR%/}
-CFG_BINDIR=${CFG_BINDIR%/}
-CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
-CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
-
-# copy build-triples to host-triples so that builds are a subset of hosts
-V_TEMP=""
-for i in $CFG_BUILD $CFG_HOST;
-do
-   echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i"
-done
-CFG_HOST=$V_TEMP
-
-# copy host-triples to target-triples so that hosts are a subset of targets
-V_TEMP=""
-for i in $CFG_HOST $CFG_TARGET;
-do
-   echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i"
-done
-CFG_TARGET=$V_TEMP
-
-step_msg "writing configuration"
-
-putvar CFG_SRC_DIR
-putvar CFG_SRC_DIR_RELATIVE
-putvar CFG_BUILD_DIR
-putvar CFG_OSTYPE
-putvar CFG_CPUTYPE
-putvar CFG_CONFIGURE_ARGS
-putvar CFG_PREFIX
-putvar CFG_HOST
-putvar CFG_TARGET
-putvar CFG_LIBDIR_RELATIVE
-putvar CFG_DISABLE_MANAGE_SUBMODULES
-putvar CFG_AARCH64_LINUX_ANDROID_NDK
-putvar CFG_ARM_LINUX_ANDROIDEABI_NDK
-putvar CFG_ARMV7_LINUX_ANDROIDEABI_NDK
-putvar CFG_I686_LINUX_ANDROID_NDK
-putvar CFG_X86_64_LINUX_ANDROID_NDK
-putvar CFG_NACL_CROSS_PATH
-putvar CFG_MANDIR
-putvar CFG_DOCDIR
-putvar CFG_BINDIR
-putvar CFG_USING_LIBCPP
-
-msg
-copy_if_changed ${CFG_SRC_DIR}src/bootstrap/mk/Makefile.in ./Makefile
-move_if_changed config.tmp config.mk
-rm -f config.tmp
-touch config.stamp
-
-if [ -z "$CFG_ENABLE_DEBUG" ]; then
-    step_msg "configured in release mode. for development consider --enable-debug"
-else
-    step_msg "complete"
-fi
-
-if [ "$CFG_SRC_DIR" = `pwd` ]; then
-    X_PY=x.py
-else
-    X_PY=${CFG_SRC_DIR_RELATIVE}x.py
-fi
-
-msg "run \`python ${X_PY} --help\`"
-msg
+try python2.7 "$@"
+try python27 "$@"
+try python2 "$@"
+exec python $script "$@"
diff --git a/src/Cargo.lock b/src/Cargo.lock
index c175198c227..123c884585c 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -94,7 +94,7 @@ dependencies = [
  "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.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.4 (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)",
 ]
 
@@ -142,10 +142,10 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -161,9 +161,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.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)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -176,7 +176,7 @@ dependencies = [
 [[package]]
 name = "cargo"
 version = "0.22.0"
-source = "git+https://github.com/rust-lang/cargo#88aa6423a164774d09abc78a24e74e8e665f651b"
+source = "git+https://github.com/rust-lang/cargo#bcf3997b1fa177afc5b6c632a6fbbf6cc75df427"
 replace = "cargo 0.22.0"
 
 [[package]]
@@ -187,6 +187,7 @@ dependencies = [
  "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargotest 0.1.0",
+ "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.11.0",
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -210,19 +211,20 @@ dependencies = [
  "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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.17 (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.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (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)",
  "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -231,22 +233,16 @@ dependencies = [
 name = "cargotest"
 version = "0.1.0"
 dependencies = [
- "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo 0.22.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)",
  "git2 0.6.6 (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)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.29 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (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)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -260,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "clap"
-version = "2.25.1"
+version = "2.26.0"
 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)",
@@ -268,8 +264,8 @@ 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.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.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)",
  "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)",
@@ -324,13 +320,30 @@ dependencies = [
 ]
 
 [[package]]
+name = "core-foundation"
+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.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "crates-io"
 version = "0.11.0"
 dependencies = [
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -348,8 +361,8 @@ dependencies = [
  "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.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)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -361,7 +374,7 @@ dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (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)",
@@ -397,8 +410,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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -473,6 +486,10 @@ name = "find_all_refs_no_cfg_test"
 version = "0.1.0"
 
 [[package]]
+name = "find_impls"
+version = "0.1.0"
+
+[[package]]
 name = "flate2"
 version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -529,7 +546,7 @@ dependencies = [
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.12 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -588,7 +605,7 @@ dependencies = [
  "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)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (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)",
 ]
 
@@ -643,10 +660,22 @@ dependencies = [
 ]
 
 [[package]]
+name = "infer_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_custom_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_lib"
+version = "0.1.0"
+
+[[package]]
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -673,13 +702,13 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core"
-version = "7.0.1"
+version = "7.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.14 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
 ]
 
@@ -698,8 +727,8 @@ 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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
  "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)",
@@ -733,7 +762,7 @@ dependencies = [
  "libc 0.2.29 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -745,7 +774,7 @@ dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (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.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -771,7 +800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lzma-sys"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -789,16 +818,16 @@ name = "mdbook"
 version = "0.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.26.2 (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)",
  "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.10 (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)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -832,7 +861,7 @@ version = "0.2.1"
 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)",
- "net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 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)",
 ]
@@ -843,7 +872,7 @@ version = "0.1.0"
 
 [[package]]
 name = "net2"
-version = "0.2.30"
+version = "0.2.31"
 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)",
@@ -859,7 +888,7 @@ version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -879,7 +908,7 @@ dependencies = [
 
 [[package]]
 name = "num-complex"
-version = "0.1.39"
+version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -928,20 +957,24 @@ dependencies = [
 ]
 
 [[package]]
+name = "omit_init_build"
+version = "0.1.0"
+
+[[package]]
 name = "open"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl"
-version = "0.9.15"
+version = "0.9.17"
 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.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -951,12 +984,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.15"
+version = "0.9.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (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)",
 ]
 
 [[package]]
@@ -1051,14 +1085,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "racer"
-version = "2.0.9"
+version = "2.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (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)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1140,20 +1172,20 @@ version = "0.1.0"
 dependencies = [
  "cargo 0.22.0 (git+https://github.com/rust-lang/cargo)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 7.1.0 (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.9 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.10.0 (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.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 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)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (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)",
 ]
@@ -1177,8 +1209,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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
 ]
 
 [[package]]
@@ -1187,8 +1219,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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
 ]
 
 [[package]]
@@ -1196,7 +1228,7 @@ name = "rls-vfs"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1204,7 +1236,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1231,7 +1263,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1295,7 +1327,6 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_mir 0.0.0",
  "syntax 0.0.0",
@@ -1432,7 +1463,6 @@ dependencies = [
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "serialize 0.0.0",
@@ -1452,6 +1482,7 @@ dependencies = [
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_errors 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -1543,7 +1574,7 @@ dependencies = [
  "num_cpus 1.6.2 (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-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
@@ -1572,6 +1603,7 @@ dependencies = [
 name = "rustc_tsan"
 version = "0.0.0"
 dependencies = [
+ "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1615,7 +1647,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1625,13 +1657,13 @@ dependencies = [
  "libc 0.2.29 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (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)",
  "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.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1660,7 +1692,7 @@ version = "0.7.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.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1670,12 +1702,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1697,7 +1729,7 @@ name = "serde_ignored"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1708,7 +1740,7 @@ dependencies = [
  "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1722,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "socket2"
-version = "0.2.1"
+version = "0.2.2"
 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)",
@@ -1826,7 +1858,6 @@ name = "syntax_ext"
 version = "0.0.0"
 dependencies = [
  "fmt_macros 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
@@ -1936,7 +1967,7 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.6.0"
+version = "0.7.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)",
@@ -1983,10 +2014,10 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.4.2"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2009,7 +2040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2057,7 +2088,7 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2146,7 +2177,7 @@ name = "xz2"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2169,8 +2200,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum cargo 0.22.0 (git+https://github.com/rust-lang/cargo)" = "<none>"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1aabf260a8f3fefa8871f16b531038c98dd9eab1cfa2c575e78c459abfa3a0"
+"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
 "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
+"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"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
 "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"
@@ -2204,7 +2237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133"
-"checksum jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da622868a84d3f4fd897f6408ba6714aabf663302802358564b384157c1a5bfa"
+"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "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"
@@ -2213,26 +2246,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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 log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
-"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8"
+"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700"
 "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 miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
-"checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566"
+"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"
 "checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd"
-"checksum num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "eb24db7f1904e67a5dfe5f7f62b82f5c963e0f777b23f98cde9c5094fc4fa179"
+"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"
 "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
 "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.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f776f1d8af832fd2c637ee182c801e8f7ea8895718a2be9914cca001f6e2c40a"
+"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5"
 "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ad95f8160d1c150c4f44d4c4959732e048ac046c37f597fe362f8bf57561ffb4"
+"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3"
 "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"
@@ -2242,7 +2275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
 "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.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
+"checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "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"
@@ -2252,21 +2285,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
-"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
+"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa1ffc66e1e1786355f22e8a958a57bd67fbf9564f522f87f31de9586715f8f6"
+"checksum rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6eea0d0590ae793fc4d281df56e01dc7531575c8ed9a72fadf5fdc7305a0d32f"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
 "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f"
-"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624"
+"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_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46"
 "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
-"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371"
+"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
@@ -2281,16 +2314,16 @@ 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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
-"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167"
+"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6"
 "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"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
-"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
+"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
 "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
-"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
+"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
diff --git a/src/Cargo.toml b/src/Cargo.toml
index 4b84272df98..ffec3eb0755 100644
--- a/src/Cargo.toml
+++ b/src/Cargo.toml
@@ -32,6 +32,11 @@ members = [
   "tools/rls/test_data/multiple_bins",
   "tools/rls/test_data/bin_lib",
   "tools/rls/test_data/reformat_with_range",
+  "tools/rls/test_data/find_impls",
+  "tools/rls/test_data/infer_bin",
+  "tools/rls/test_data/infer_custom_bin",
+  "tools/rls/test_data/infer_lib",
+  "tools/rls/test_data/omit_init_build",
 ]
 
 # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 65c1088f547..e543b8c070b 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -73,16 +73,18 @@ The script accepts commands, flags, and arguments to determine what to do:
 
 ## Configuring rustbuild
 
-There are currently two primary methods for configuring the rustbuild build
-system. First, the `./configure` options serialized in `config.mk` will be
-parsed and read. That is, if any `./configure` options are passed, they'll be
-handled naturally.
+There are currently two methods for configuring the rustbuild build system.
+
+First, rustbuild offers a TOML-based configuration system with a `config.toml`
+file. An example of this configuration can be found at `config.toml.example`,
+and the configuration file can also be passed as `--config path/to/config.toml`
+if the build system is being invoked manually (via the python script).
 
-Next, rustbuild offers a TOML-based configuration system with a `config.toml`
-file in the same location as `config.mk`. An example of this configuration can
-be found at `config.toml.example`, and the configuration file
-can also be passed as `--config path/to/config.toml` if the build system is
-being invoked manually (via the python script).
+Next, the `./configure` options serialized in `config.mk` will be
+parsed and read. That is, if any `./configure` options are passed, they'll be
+handled naturally. `./configure` should almost never be used for local
+installations, and is primarily useful for CI. Prefer to customize behavior
+using `config.toml`.
 
 Finally, rustbuild makes use of the [gcc-rs crate] which has [its own
 method][env-vars] of configuring C compilers and C flags via environment
@@ -310,17 +312,18 @@ After that, each module in rustbuild should have enough documentation to keep
 you up and running. Some general areas that you may be interested in modifying
 are:
 
-* Adding a new build tool? Take a look at `bootstrap/step.rs` for examples of
+* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
   other tools.
 * Adding a new compiler crate? Look no further! Adding crates can be done by
   adding a new directory with `Cargo.toml` followed by configuring all
   `Cargo.toml` files accordingly.
-* Adding a new dependency from crates.io? We're still working on that, so hold
-  off on that for now.
-* Adding a new configuration option? Take a look at `bootstrap/config.rs` or
-  perhaps `bootstrap/flags.rs` and then modify the build elsewhere to read that
-  option.
+* Adding a new dependency from crates.io? This should just work inside the
+  compiler artifacts stage (everything other than libtest and libstd).
+* Adding a new configuration option? You'll want to modify `bootstrap/flags.rs`
+  for command line flags and then `bootstrap/config.rs` to copy the flags to the
+  `Config` struct.
 * Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
 
-If you have any questions feel free to reach out on `#rust-internals` on IRC or
-open an issue in the bug tracker!
+If you have any questions feel free to reach out on `#rust-infra` on IRC or ask on
+internals.rust-lang.org. When you encounter bugs, please file issues on the
+rust-lang/rust issue tracker.
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index f6ed4ee91b3..0baca9e58f4 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -237,9 +237,13 @@ fn main() {
             }
         }
 
-        if target.contains("pc-windows-msvc") {
-            cmd.arg("-Z").arg("unstable-options");
-            cmd.arg("-C").arg("target-feature=+crt-static");
+        if let Ok(s) = env::var("RUSTC_CRT_STATIC") {
+            if s == "true" {
+                cmd.arg("-C").arg("target-feature=+crt-static");
+            }
+            if s == "false" {
+                cmd.arg("-C").arg("target-feature=-crt-static");
+            }
         }
 
         // Force all crates compiled by this compiler to (a) be unstable and (b)
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9369a55ccb9..4c1bd7bdca9 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -167,6 +167,141 @@ def format_build_time(duration):
     return str(datetime.timedelta(seconds=int(duration)))
 
 
+def default_build_triple():
+    """Build triple as in LLVM"""
+    default_encoding = sys.getdefaultencoding()
+    try:
+        ostype = subprocess.check_output(
+            ['uname', '-s']).strip().decode(default_encoding)
+        cputype = subprocess.check_output(
+            ['uname', '-m']).strip().decode(default_encoding)
+    except (subprocess.CalledProcessError, OSError):
+        if sys.platform == 'win32':
+            return 'x86_64-pc-windows-msvc'
+        err = "uname not found"
+        sys.exit(err)
+
+    # The goal here is to come up with the same triple as LLVM would,
+    # at least for the subset of platforms we're willing to target.
+    ostype_mapper = {
+        'Bitrig': 'unknown-bitrig',
+        'Darwin': 'apple-darwin',
+        'DragonFly': 'unknown-dragonfly',
+        'FreeBSD': 'unknown-freebsd',
+        'Haiku': 'unknown-haiku',
+        'NetBSD': 'unknown-netbsd',
+        'OpenBSD': 'unknown-openbsd'
+    }
+
+    # Consider the direct transformation first and then the special cases
+    if ostype in ostype_mapper:
+        ostype = ostype_mapper[ostype]
+    elif ostype == 'Linux':
+        os_from_sp = subprocess.check_output(
+            ['uname', '-o']).strip().decode(default_encoding)
+        if os_from_sp == 'Android':
+            ostype = 'linux-android'
+        else:
+            ostype = 'unknown-linux-gnu'
+    elif ostype == 'SunOS':
+        ostype = 'sun-solaris'
+        # On Solaris, uname -m will return a machine classification instead
+        # of a cpu type, so uname -p is recommended instead.  However, the
+        # output from that option is too generic for our purposes (it will
+        # always emit 'i386' on x86/amd64 systems).  As such, isainfo -k
+        # must be used instead.
+        try:
+            cputype = subprocess.check_output(
+                ['isainfo', '-k']).strip().decode(default_encoding)
+        except (subprocess.CalledProcessError, OSError):
+            err = "isainfo not found"
+            sys.exit(err)
+    elif ostype.startswith('MINGW'):
+        # msys' `uname` does not print gcc configuration, but prints msys
+        # configuration. so we cannot believe `uname -m`:
+        # msys1 is always i686 and msys2 is always x86_64.
+        # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
+        # MINGW64 on x86_64.
+        ostype = 'pc-windows-gnu'
+        cputype = 'i686'
+        if os.environ.get('MSYSTEM') == 'MINGW64':
+            cputype = 'x86_64'
+    elif ostype.startswith('MSYS'):
+        ostype = 'pc-windows-gnu'
+    elif ostype.startswith('CYGWIN_NT'):
+        cputype = 'i686'
+        if ostype.endswith('WOW64'):
+            cputype = 'x86_64'
+        ostype = 'pc-windows-gnu'
+    else:
+        err = "unknown OS type: {}".format(ostype)
+        sys.exit(err)
+
+    cputype_mapper = {
+        'BePC': 'i686',
+        'aarch64': 'aarch64',
+        'amd64': 'x86_64',
+        'arm64': 'aarch64',
+        'i386': 'i686',
+        'i486': 'i686',
+        'i686': 'i686',
+        'i786': 'i686',
+        'powerpc': 'powerpc',
+        'powerpc64': 'powerpc64',
+        'powerpc64le': 'powerpc64le',
+        'ppc': 'powerpc',
+        'ppc64': 'powerpc64',
+        'ppc64le': 'powerpc64le',
+        's390x': 's390x',
+        'x64': 'x86_64',
+        'x86': 'i686',
+        'x86-64': 'x86_64',
+        'x86_64': 'x86_64'
+    }
+
+    # Consider the direct transformation first and then the special cases
+    if cputype in cputype_mapper:
+        cputype = cputype_mapper[cputype]
+    elif cputype in {'xscale', 'arm'}:
+        cputype = 'arm'
+        if ostype == 'linux-android':
+            ostype = 'linux-androideabi'
+    elif cputype == 'armv6l':
+        cputype = 'arm'
+        if ostype == 'linux-android':
+            ostype = 'linux-androideabi'
+        else:
+            ostype += 'eabihf'
+    elif cputype in {'armv7l', 'armv8l'}:
+        cputype = 'armv7'
+        if ostype == 'linux-android':
+            ostype = 'linux-androideabi'
+        else:
+            ostype += 'eabihf'
+    elif cputype == 'mips':
+        if sys.byteorder == 'big':
+            cputype = 'mips'
+        elif sys.byteorder == 'little':
+            cputype = 'mipsel'
+        else:
+            raise ValueError("unknown byteorder: {}".format(sys.byteorder))
+    elif cputype == 'mips64':
+        if sys.byteorder == 'big':
+            cputype = 'mips64'
+        elif sys.byteorder == 'little':
+            cputype = 'mips64el'
+        else:
+            raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
+        # only the n64 ABI is supported, indicate it
+        ostype += 'abi64'
+    elif cputype == 'sparcv9':
+        pass
+    else:
+        err = "unknown cpu type: {}".format(cputype)
+        sys.exit(err)
+
+    return "{}-{}".format(cputype, ostype)
+
 class RustBuild(object):
     """Provide all the methods required to build Rust"""
     def __init__(self):
@@ -177,7 +312,6 @@ class RustBuild(object):
         self.build = ''
         self.build_dir = os.path.join(os.getcwd(), "build")
         self.clean = False
-        self.config_mk = ''
         self.config_toml = ''
         self.printed = False
         self.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
@@ -374,26 +508,6 @@ class RustBuild(object):
                 return self.get_string(value) or value.strip()
         return None
 
-    def get_mk(self, key):
-        """Returns the value of the given key in config.mk, otherwise returns None
-
-        >>> rb = RustBuild()
-        >>> rb.config_mk = 'key := value\\n'
-        >>> rb.get_mk('key')
-        'value'
-
-        If the key does not exists, the result is None:
-
-        >>> rb.get_mk('does_not_exists') == None
-        True
-        """
-        for line in iter(self.config_mk.splitlines()):
-            if line.startswith(key + ' '):
-                var = line[line.find(':=') + 2:].strip()
-                if var != '':
-                    return var
-        return None
-
     def cargo(self):
         """Return config path for cargo"""
         return self.program_config('cargo')
@@ -407,7 +521,6 @@ class RustBuild(object):
 
         >>> rb = RustBuild()
         >>> rb.config_toml = 'rustc = "rustc"\\n'
-        >>> rb.config_mk = 'CFG_LOCAL_RUST_ROOT := /tmp/rust\\n'
         >>> rb.program_config('rustc')
         'rustc'
         >>> cargo_path = rb.program_config('cargo')
@@ -415,7 +528,6 @@ class RustBuild(object):
         ... "bin", "cargo")
         True
         >>> rb.config_toml = ''
-        >>> rb.config_mk = ''
         >>> cargo_path = rb.program_config('cargo')
         >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(),
         ... "bin", "cargo")
@@ -424,10 +536,6 @@ class RustBuild(object):
         config = self.get_toml(program)
         if config:
             return config
-        config = self.get_mk('CFG_LOCAL_RUST_ROOT')
-        if config:
-            return os.path.join(config, "bin", "{}{}".format(
-                program, self.exe_suffix()))
         return os.path.join(self.bin_root(), "bin", "{}{}".format(
             program, self.exe_suffix()))
 
@@ -439,10 +547,14 @@ class RustBuild(object):
         'devel'
         """
         start = line.find('"')
-        if start == -1:
-            return None
-        end = start + 1 + line[start + 1:].find('"')
-        return line[start + 1:end]
+        if start != -1:
+            end = start + 1 + line[start + 1:].find('"')
+            return line[start + 1:end]
+        start = line.find('\'')
+        if start != -1:
+            end = start + 1 + line[start + 1:].find('\'')
+            return line[start + 1:end]
+        return None
 
     @staticmethod
     def exe_suffix():
@@ -521,154 +633,12 @@ class RustBuild(object):
         config = self.get_toml('build')
         if config:
             return config
-        config = self.get_mk('CFG_BUILD')
-        if config:
-            return config
-        try:
-            ostype = subprocess.check_output(
-                ['uname', '-s']).strip().decode(default_encoding)
-            cputype = subprocess.check_output(
-                ['uname', '-m']).strip().decode(default_encoding)
-        except (subprocess.CalledProcessError, OSError):
-            if sys.platform == 'win32':
-                return 'x86_64-pc-windows-msvc'
-            err = "uname not found"
-            if self.verbose:
-                raise Exception(err)
-            sys.exit(err)
-
-        # The goal here is to come up with the same triple as LLVM would,
-        # at least for the subset of platforms we're willing to target.
-        ostype_mapper = {
-            'Bitrig': 'unknown-bitrig',
-            'Darwin': 'apple-darwin',
-            'DragonFly': 'unknown-dragonfly',
-            'FreeBSD': 'unknown-freebsd',
-            'Haiku': 'unknown-haiku',
-            'NetBSD': 'unknown-netbsd',
-            'OpenBSD': 'unknown-openbsd'
-        }
-
-        # Consider the direct transformation first and then the special cases
-        if ostype in ostype_mapper:
-            ostype = ostype_mapper[ostype]
-        elif ostype == 'Linux':
-            os_from_sp = subprocess.check_output(
-                ['uname', '-o']).strip().decode(default_encoding)
-            if os_from_sp == 'Android':
-                ostype = 'linux-android'
-            else:
-                ostype = 'unknown-linux-gnu'
-        elif ostype == 'SunOS':
-            ostype = 'sun-solaris'
-            # On Solaris, uname -m will return a machine classification instead
-            # of a cpu type, so uname -p is recommended instead.  However, the
-            # output from that option is too generic for our purposes (it will
-            # always emit 'i386' on x86/amd64 systems).  As such, isainfo -k
-            # must be used instead.
-            try:
-                cputype = subprocess.check_output(
-                    ['isainfo', '-k']).strip().decode(default_encoding)
-            except (subprocess.CalledProcessError, OSError):
-                err = "isainfo not found"
-                if self.verbose:
-                    raise Exception(err)
-                sys.exit(err)
-        elif ostype.startswith('MINGW'):
-            # msys' `uname` does not print gcc configuration, but prints msys
-            # configuration. so we cannot believe `uname -m`:
-            # msys1 is always i686 and msys2 is always x86_64.
-            # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
-            # MINGW64 on x86_64.
-            ostype = 'pc-windows-gnu'
-            cputype = 'i686'
-            if os.environ.get('MSYSTEM') == 'MINGW64':
-                cputype = 'x86_64'
-        elif ostype.startswith('MSYS'):
-            ostype = 'pc-windows-gnu'
-        elif ostype.startswith('CYGWIN_NT'):
-            cputype = 'i686'
-            if ostype.endswith('WOW64'):
-                cputype = 'x86_64'
-            ostype = 'pc-windows-gnu'
-        else:
-            err = "unknown OS type: {}".format(ostype)
-            if self.verbose:
-                raise ValueError(err)
-            sys.exit(err)
-
-        cputype_mapper = {
-            'BePC': 'i686',
-            'aarch64': 'aarch64',
-            'amd64': 'x86_64',
-            'arm64': 'aarch64',
-            'i386': 'i686',
-            'i486': 'i686',
-            'i686': 'i686',
-            'i786': 'i686',
-            'powerpc': 'powerpc',
-            'powerpc64': 'powerpc64',
-            'powerpc64le': 'powerpc64le',
-            'ppc': 'powerpc',
-            'ppc64': 'powerpc64',
-            'ppc64le': 'powerpc64le',
-            's390x': 's390x',
-            'x64': 'x86_64',
-            'x86': 'i686',
-            'x86-64': 'x86_64',
-            'x86_64': 'x86_64'
-        }
-
-        # Consider the direct transformation first and then the special cases
-        if cputype in cputype_mapper:
-            cputype = cputype_mapper[cputype]
-        elif cputype in {'xscale', 'arm'}:
-            cputype = 'arm'
-            if ostype == 'linux-android':
-                ostype = 'linux-androideabi'
-        elif cputype == 'armv6l':
-            cputype = 'arm'
-            if ostype == 'linux-android':
-                ostype = 'linux-androideabi'
-            else:
-                ostype += 'eabihf'
-        elif cputype in {'armv7l', 'armv8l'}:
-            cputype = 'armv7'
-            if ostype == 'linux-android':
-                ostype = 'linux-androideabi'
-            else:
-                ostype += 'eabihf'
-        elif cputype == 'mips':
-            if sys.byteorder == 'big':
-                cputype = 'mips'
-            elif sys.byteorder == 'little':
-                cputype = 'mipsel'
-            else:
-                raise ValueError("unknown byteorder: {}".format(sys.byteorder))
-        elif cputype == 'mips64':
-            if sys.byteorder == 'big':
-                cputype = 'mips64'
-            elif sys.byteorder == 'little':
-                cputype = 'mips64el'
-            else:
-                raise ValueError('unknown byteorder: {}'.format(sys.byteorder))
-            # only the n64 ABI is supported, indicate it
-            ostype += 'abi64'
-        elif cputype == 'sparcv9':
-            pass
-        else:
-            err = "unknown cpu type: {}".format(cputype)
-            if self.verbose:
-                raise ValueError(err)
-            sys.exit(err)
-
-        return "{}-{}".format(cputype, ostype)
+        return default_build_triple()
 
     def update_submodules(self):
         """Update submodules"""
         if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \
-                self.get_toml('submodules') == "false" or \
-                self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1":
+                self.get_toml('submodules') == "false":
             return
         print('Updating submodules')
         default_encoding = sys.getdefaultencoding()
@@ -680,11 +650,9 @@ class RustBuild(object):
         ).decode(default_encoding).splitlines()]
         submodules = [module for module in submodules
                       if not ((module.endswith("llvm") and
-                               (self.get_toml('llvm-config') or
-                                self.get_mk('CFG_LLVM_ROOT'))) or
+                               self.get_toml('llvm-config')) or
                               (module.endswith("jemalloc") and
-                               (self.get_toml('jemalloc') or
-                                self.get_mk('CFG_JEMALLOC_ROOT'))))]
+                               self.get_toml('jemalloc')))]
         run(["git", "submodule", "update",
              "--init", "--recursive"] + submodules,
             cwd=self.rust_root, verbose=self.verbose)
@@ -721,21 +689,15 @@ def bootstrap():
             build.config_toml = config.read()
     except:
         pass
-    try:
-        build.config_mk = open('config.mk').read()
-    except:
-        pass
 
     if '\nverbose = 2' in build.config_toml:
         build.verbose = 2
     elif '\nverbose = 1' in build.config_toml:
         build.verbose = 1
 
-    build.use_vendored_sources = '\nvendor = true' in build.config_toml or \
-                                 'CFG_ENABLE_VENDOR' in build.config_mk
+    build.use_vendored_sources = '\nvendor = true' in build.config_toml
 
-    build.use_locked_deps = '\nlocked-deps = true' in build.config_toml or \
-                            'CFG_ENABLE_LOCKED_DEPS' in build.config_mk
+    build.use_locked_deps = '\nlocked-deps = true' in build.config_toml
 
     if 'SUDO_USER' in os.environ and not build.use_vendored_sources:
         if os.environ.get('USER') != os.environ['SUDO_USER']:
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 91dddc7b5bc..298f6a004a2 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -193,7 +193,7 @@ pub struct ShouldRun<'a> {
 impl<'a> ShouldRun<'a> {
     fn new(builder: &'a Builder) -> ShouldRun<'a> {
         ShouldRun {
-            builder: builder,
+            builder,
             paths: BTreeSet::new(),
             is_really_default: true, // by default no additional conditions
         }
@@ -257,7 +257,7 @@ impl<'a> Builder<'a> {
             Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
-                doc::Reference, doc::Rustdoc),
+                doc::Reference, doc::Rustdoc, doc::CargoBook),
             Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
                 dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
                 dist::Rls, dist::Extended, dist::HashSign),
@@ -278,9 +278,9 @@ impl<'a> Builder<'a> {
         };
 
         let builder = Builder {
-            build: build,
+            build,
             top_stage: build.config.stage.unwrap_or(2),
-            kind: kind,
+            kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
         };
@@ -309,9 +309,9 @@ impl<'a> Builder<'a> {
         };
 
         let builder = Builder {
-            build: build,
+            build,
             top_stage: build.config.stage.unwrap_or(2),
-            kind: kind,
+            kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
         };
@@ -503,6 +503,10 @@ impl<'a> Builder<'a> {
             cargo.env("RUSTC_METADATA_SUFFIX", "rustc");
         }
 
+        if let Some(x) = self.crt_static(target) {
+            cargo.env("RUSTC_CRT_STATIC", x.to_string());
+        }
+
         // Enable usage of unstable features
         cargo.env("RUSTC_BOOTSTRAP", "1");
         self.add_rust_test_threads(&mut cargo);
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 1823dd4ebc0..92fb2105b7c 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -872,7 +872,7 @@ impl Step for CrateLibrustc {
             builder.ensure(CrateLibrustc {
                 compiler,
                 target: run.target,
-                test_kind: test_kind,
+                test_kind,
                 krate: name,
             });
         };
@@ -934,8 +934,8 @@ impl Step for Crate {
             builder.ensure(Crate {
                 compiler,
                 target: run.target,
-                mode: mode,
-                test_kind: test_kind,
+                mode,
+                test_kind,
                 krate: name,
             });
         };
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 33c3638a894..335e1690a2e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -74,13 +74,21 @@ impl Step for Std {
             let from = builder.compiler(1, build.build);
             builder.ensure(Std {
                 compiler: from,
-                target: target,
+                target,
             });
             println!("Uplifting stage1 std ({} -> {})", from.host, target);
+
+            // Even if we're not building std this stage, the new sysroot must
+            // still contain the musl startup objects.
+            if target.contains("musl") && !target.contains("mips") {
+                let libdir = builder.sysroot_libdir(compiler, target);
+                copy_musl_third_party_objects(build, target, &libdir);
+            }
+
             builder.ensure(StdLink {
                 compiler: from,
                 target_compiler: compiler,
-                target: target,
+                target,
             });
             return;
         }
@@ -89,6 +97,11 @@ impl Step for Std {
         println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
                 &compiler.host, target);
 
+        if target.contains("musl") && !target.contains("mips") {
+            let libdir = builder.sysroot_libdir(compiler, target);
+            copy_musl_third_party_objects(build, target, &libdir);
+        }
+
         let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
         build.clear_if_dirty(&out_dir, &builder.rustc(compiler));
         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
@@ -100,11 +113,25 @@ impl Step for Std {
         builder.ensure(StdLink {
             compiler: builder.compiler(compiler.stage, build.build),
             target_compiler: compiler,
-            target: target,
+            target,
         });
     }
 }
 
+/// Copies the crt(1,i,n).o startup objects
+///
+/// Since musl supports fully static linking, we can cross link for it even
+/// with a glibc-targeting toolchain, given we have the appropriate startup
+/// files. As those shipped with glibc won't work, copy the ones provided by
+/// musl so we have them on linux-gnu hosts.
+fn copy_musl_third_party_objects(build: &Build,
+                                 target: Interned<String>,
+                                 into: &Path) {
+    for &obj in &["crt1.o", "crti.o", "crtn.o"] {
+        copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
+    }
+}
+
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
 pub fn std_cargo(build: &Build,
@@ -189,10 +216,6 @@ impl Step for StdLink {
         let libdir = builder.sysroot_libdir(target_compiler, target);
         add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target));
 
-        if target.contains("musl") && !target.contains("mips") {
-            copy_musl_third_party_objects(build, target, &libdir);
-        }
-
         if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
             // The sanitizers are only built in stage1 or above, so the dylibs will
             // be missing in stage0 and causes panic. See the `std()` function above
@@ -202,21 +225,12 @@ impl Step for StdLink {
 
         builder.ensure(tool::CleanTools {
             compiler: target_compiler,
-            target: target,
+            target,
             mode: Mode::Libstd,
         });
     }
 }
 
-/// Copies the crt(1,i,n).o startup objects
-///
-/// Only required for musl targets that statically link to libc
-fn copy_musl_third_party_objects(build: &Build, target: Interned<String>, into: &Path) {
-    for &obj in &["crt1.o", "crti.o", "crtn.o"] {
-        copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
-    }
-}
-
 fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) {
     for &sanitizer in &["asan", "tsan"] {
         let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform);
@@ -326,13 +340,13 @@ impl Step for Test {
         if build.force_use_stage1(compiler, target) {
             builder.ensure(Test {
                 compiler: builder.compiler(1, build.build),
-                target: target,
+                target,
             });
             println!("Uplifting stage1 test ({} -> {})", &build.build, target);
             builder.ensure(TestLink {
                 compiler: builder.compiler(1, build.build),
                 target_compiler: compiler,
-                target: target,
+                target,
             });
             return;
         }
@@ -351,7 +365,7 @@ impl Step for Test {
         builder.ensure(TestLink {
             compiler: builder.compiler(compiler.stage, build.build),
             target_compiler: compiler,
-            target: target,
+            target,
         });
     }
 }
@@ -398,7 +412,7 @@ impl Step for TestLink {
                     &libtest_stamp(build, compiler, target));
         builder.ensure(tool::CleanTools {
             compiler: target_compiler,
-            target: target,
+            target,
             mode: Mode::Libtest,
         });
     }
@@ -445,7 +459,7 @@ impl Step for Rustc {
         if build.force_use_stage1(compiler, target) {
             builder.ensure(Rustc {
                 compiler: builder.compiler(1, build.build),
-                target: target,
+                target,
             });
             println!("Uplifting stage1 rustc ({} -> {})", &build.build, target);
             builder.ensure(RustcLink {
@@ -581,7 +595,7 @@ impl Step for RustcLink {
                        &librustc_stamp(build, compiler, target));
         builder.ensure(tool::CleanTools {
             compiler: target_compiler,
-            target: target,
+            target,
             mode: Mode::Librustc,
         });
     }
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 5975c88c560..2c25f374e12 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -10,12 +10,12 @@
 
 //! Serialized configuration of a build.
 //!
-//! This module implements parsing `config.mk` and `config.toml` configuration
-//! files to tweak how the build runs.
+//! This module implements parsing `config.toml` configuration files to tweak
+//! how the build runs.
 
 use std::collections::HashMap;
 use std::env;
-use std::fs::{self, File};
+use std::fs::File;
 use std::io::prelude::*;
 use std::path::PathBuf;
 use std::process;
@@ -23,7 +23,7 @@ use std::cmp;
 
 use num_cpus;
 use toml;
-use util::{exe, push_exe_path};
+use util::exe;
 use cache::{INTERNER, Interned};
 use flags::Flags;
 pub use flags::Subcommand;
@@ -124,14 +124,12 @@ pub struct Config {
     pub nodejs: Option<PathBuf>,
     pub gdb: Option<PathBuf>,
     pub python: Option<PathBuf>,
-    pub configure_args: Vec<String>,
     pub openssl_static: bool,
-
+    pub configure_args: Vec<String>,
 
     // These are either the stage0 downloaded binaries or the locally installed ones.
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
-
 }
 
 /// Per-target configuration stored in the global configuration structure.
@@ -143,6 +141,7 @@ pub struct Target {
     pub cc: Option<PathBuf>,
     pub cxx: Option<PathBuf>,
     pub ndk: Option<PathBuf>,
+    pub crt_static: Option<bool>,
     pub musl_root: Option<PathBuf>,
     pub qemu_rootfs: Option<PathBuf>,
 }
@@ -189,6 +188,8 @@ struct Build {
     sanitizers: Option<bool>,
     profiler: Option<bool>,
     openssl_static: Option<bool>,
+    configure_args: Option<Vec<String>>,
+    local_rebuild: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
@@ -218,6 +219,7 @@ struct Llvm {
     targets: Option<String>,
     experimental_targets: Option<String>,
     link_jobs: Option<u32>,
+    link_shared: Option<bool>,
 }
 
 #[derive(Deserialize, Default, Clone)]
@@ -264,6 +266,9 @@ struct Rust {
     debuginfo_tests: Option<bool>,
     codegen_tests: Option<bool>,
     ignore_git: Option<bool>,
+    debug: Option<bool>,
+    dist_src: Option<bool>,
+    quiet_tests: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -275,6 +280,7 @@ struct TomlTarget {
     cc: Option<String>,
     cxx: Option<String>,
     android_ndk: Option<String>,
+    crt_static: Option<bool>,
     musl_root: Option<String>,
     qemu_rootfs: Option<String>,
 }
@@ -372,6 +378,8 @@ impl Config {
         set(&mut config.sanitizers, build.sanitizers);
         set(&mut config.profiler, build.profiler);
         set(&mut config.openssl_static, build.openssl_static);
+        set(&mut config.configure_args, build.configure_args);
+        set(&mut config.local_rebuild, build.local_rebuild);
         config.verbose = cmp::max(config.verbose, flags.verbose);
 
         if let Some(ref install) = toml.install {
@@ -383,6 +391,17 @@ impl Config {
             config.mandir = install.mandir.clone().map(PathBuf::from);
         }
 
+        // Store off these values as options because if they're not provided
+        // we'll infer default values for them later
+        let mut llvm_assertions = None;
+        let mut debuginfo_lines = None;
+        let mut debuginfo_only_std = None;
+        let mut debug = None;
+        let mut debug_jemalloc = None;
+        let mut debuginfo = None;
+        let mut debug_assertions = None;
+        let mut optimize = None;
+
         if let Some(ref llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => {
@@ -395,36 +414,35 @@ impl Config {
             }
             set(&mut config.ninja, llvm.ninja);
             set(&mut config.llvm_enabled, llvm.enabled);
-            set(&mut config.llvm_assertions, llvm.assertions);
+            llvm_assertions = llvm.assertions;
             set(&mut config.llvm_optimize, llvm.optimize);
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
             set(&mut config.llvm_version_check, llvm.version_check);
             set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
+            set(&mut config.llvm_link_shared, llvm.link_shared);
             config.llvm_targets = llvm.targets.clone();
             config.llvm_experimental_targets = llvm.experimental_targets.clone();
             config.llvm_link_jobs = llvm.link_jobs;
         }
 
         if let Some(ref rust) = toml.rust {
-            set(&mut config.rust_debug_assertions, rust.debug_assertions);
-            set(&mut config.rust_debuginfo, rust.debuginfo);
-            set(&mut config.rust_debuginfo_lines, rust.debuginfo_lines);
-            set(&mut config.rust_debuginfo_only_std, rust.debuginfo_only_std);
-            set(&mut config.rust_optimize, rust.optimize);
+            debug = rust.debug;
+            debug_assertions = rust.debug_assertions;
+            debuginfo = rust.debuginfo;
+            debuginfo_lines = rust.debuginfo_lines;
+            debuginfo_only_std = rust.debuginfo_only_std;
+            optimize = rust.optimize;
+            debug_jemalloc = rust.debug_jemalloc;
             set(&mut config.rust_optimize_tests, rust.optimize_tests);
             set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
             set(&mut config.codegen_tests, rust.codegen_tests);
             set(&mut config.rust_rpath, rust.rpath);
-            set(&mut config.debug_jemalloc, rust.debug_jemalloc);
             set(&mut config.use_jemalloc, rust.use_jemalloc);
             set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel.clone());
-
-            // on the dev channel, ignore_git should be true by default
-            // on other channels it should be false by default
-            config.ignore_git = config.channel == "dev";
             set(&mut config.ignore_git, rust.ignore_git);
-
+            set(&mut config.rust_dist_src, rust.dist_src);
+            set(&mut config.quiet_tests, rust.quiet_tests);
             config.rustc_default_linker = rust.default_linker.clone();
             config.rustc_default_ar = rust.default_ar.clone();
             config.musl_root = rust.musl_root.clone().map(PathBuf::from);
@@ -451,6 +469,7 @@ impl Config {
                 }
                 target.cxx = cfg.cxx.clone().map(PathBuf::from);
                 target.cc = cfg.cc.clone().map(PathBuf::from);
+                target.crt_static = cfg.crt_static.clone();
                 target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
                 target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
 
@@ -478,224 +497,26 @@ impl Config {
             None => stage0_root.join(exe("cargo", &config.build)),
         };
 
-        // compat with `./configure` while we're still using that
-        if fs::metadata("config.mk").is_ok() {
-            config.update_with_config_mk();
-        }
-
-        config
-    }
+        // Now that we've reached the end of our configuration, infer the
+        // default values for all options that we haven't otherwise stored yet.
 
-    /// "Temporary" routine to parse `config.mk` into this configuration.
-    ///
-    /// While we still have `./configure` this implements the ability to decode
-    /// that configuration into this. This isn't exactly a full-blown makefile
-    /// parser, but hey it gets the job done!
-    fn update_with_config_mk(&mut self) {
-        let mut config = String::new();
-        File::open("config.mk").unwrap().read_to_string(&mut config).unwrap();
-        for line in config.lines() {
-            let mut parts = line.splitn(2, ":=").map(|s| s.trim());
-            let key = parts.next().unwrap();
-            let value = match parts.next() {
-                Some(n) if n.starts_with('\"') => &n[1..n.len() - 1],
-                Some(n) => n,
-                None => continue
-            };
-
-            macro_rules! check {
-                ($(($name:expr, $val:expr),)*) => {
-                    if value == "1" {
-                        $(
-                            if key == concat!("CFG_ENABLE_", $name) {
-                                $val = true;
-                                continue
-                            }
-                            if key == concat!("CFG_DISABLE_", $name) {
-                                $val = false;
-                                continue
-                            }
-                        )*
-                    }
-                }
-            }
+        let default = config.channel == "nightly";
+        config.llvm_assertions = llvm_assertions.unwrap_or(default);
 
-            check! {
-                ("MANAGE_SUBMODULES", self.submodules),
-                ("COMPILER_DOCS", self.compiler_docs),
-                ("DOCS", self.docs),
-                ("LLVM_ASSERTIONS", self.llvm_assertions),
-                ("LLVM_RELEASE_DEBUGINFO", self.llvm_release_debuginfo),
-                ("OPTIMIZE_LLVM", self.llvm_optimize),
-                ("LLVM_VERSION_CHECK", self.llvm_version_check),
-                ("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
-                ("LLVM_LINK_SHARED", self.llvm_link_shared),
-                ("OPTIMIZE", self.rust_optimize),
-                ("DEBUG_ASSERTIONS", self.rust_debug_assertions),
-                ("DEBUGINFO", self.rust_debuginfo),
-                ("DEBUGINFO_LINES", self.rust_debuginfo_lines),
-                ("DEBUGINFO_ONLY_STD", self.rust_debuginfo_only_std),
-                ("JEMALLOC", self.use_jemalloc),
-                ("DEBUG_JEMALLOC", self.debug_jemalloc),
-                ("RPATH", self.rust_rpath),
-                ("OPTIMIZE_TESTS", self.rust_optimize_tests),
-                ("DEBUGINFO_TESTS", self.rust_debuginfo_tests),
-                ("QUIET_TESTS", self.quiet_tests),
-                ("LOCAL_REBUILD", self.local_rebuild),
-                ("NINJA", self.ninja),
-                ("CODEGEN_TESTS", self.codegen_tests),
-                ("LOCKED_DEPS", self.locked_deps),
-                ("VENDOR", self.vendor),
-                ("FULL_BOOTSTRAP", self.full_bootstrap),
-                ("EXTENDED", self.extended),
-                ("SANITIZERS", self.sanitizers),
-                ("PROFILER", self.profiler),
-                ("DIST_SRC", self.rust_dist_src),
-                ("CARGO_OPENSSL_STATIC", self.openssl_static),
-            }
+        let default = match &config.channel[..] {
+            "stable" | "beta" | "nightly" => true,
+            _ => false,
+        };
+        config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default);
+        config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default);
 
-            match key {
-                "CFG_BUILD" if value.len() > 0 => self.build = INTERNER.intern_str(value),
-                "CFG_HOST" if value.len() > 0 => {
-                    self.hosts.extend(value.split(" ").map(|s| INTERNER.intern_str(s)));
+        let default = debug == Some(true);
+        config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
+        config.rust_debuginfo = debuginfo.unwrap_or(default);
+        config.rust_debug_assertions = debug_assertions.unwrap_or(default);
+        config.rust_optimize = optimize.unwrap_or(!default);
 
-                }
-                "CFG_TARGET" if value.len() > 0 => {
-                    self.targets.extend(value.split(" ").map(|s| INTERNER.intern_str(s)));
-                }
-                "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => {
-                    self.llvm_experimental_targets = Some(value.to_string());
-                }
-                "CFG_MUSL_ROOT" if value.len() > 0 => {
-                    self.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("x86_64-unknown-linux-musl");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_MUSL_ROOT_I686" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("i686-unknown-linux-musl");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_MUSL_ROOT_ARM" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("arm-unknown-linux-musleabi");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("arm-unknown-linux-musleabihf");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("armv7-unknown-linux-musleabihf");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.musl_root = Some(parse_configure_path(value));
-                }
-                "CFG_DEFAULT_AR" if value.len() > 0 => {
-                    self.rustc_default_ar = Some(value.to_string());
-                }
-                "CFG_DEFAULT_LINKER" if value.len() > 0 => {
-                    self.rustc_default_linker = Some(value.to_string());
-                }
-                "CFG_GDB" if value.len() > 0 => {
-                    self.gdb = Some(parse_configure_path(value));
-                }
-                "CFG_RELEASE_CHANNEL" => {
-                    self.channel = value.to_string();
-                }
-                "CFG_PREFIX" => {
-                    self.prefix = Some(PathBuf::from(value));
-                }
-                "CFG_SYSCONFDIR" => {
-                    self.sysconfdir = Some(PathBuf::from(value));
-                }
-                "CFG_DOCDIR" => {
-                    self.docdir = Some(PathBuf::from(value));
-                }
-                "CFG_BINDIR" => {
-                    self.bindir = Some(PathBuf::from(value));
-                }
-                "CFG_LIBDIR" => {
-                    self.libdir = Some(PathBuf::from(value));
-                }
-                "CFG_LIBDIR_RELATIVE" => {
-                    self.libdir_relative = Some(PathBuf::from(value));
-                }
-                "CFG_MANDIR" => {
-                    self.mandir = Some(PathBuf::from(value));
-                }
-                "CFG_LLVM_ROOT" if value.len() > 0 => {
-                    let target = self.target_config.entry(self.build.clone())
-                                     .or_insert(Target::default());
-                    let root = parse_configure_path(value);
-                    target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"]));
-                }
-                "CFG_JEMALLOC_ROOT" if value.len() > 0 => {
-                    let target = self.target_config.entry(self.build.clone())
-                                     .or_insert(Target::default());
-                    target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a"));
-                }
-                "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("arm-linux-androideabi");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.ndk = Some(parse_configure_path(value));
-                }
-                "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("armv7-linux-androideabi");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.ndk = Some(parse_configure_path(value));
-                }
-                "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("i686-linux-android");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.ndk = Some(parse_configure_path(value));
-                }
-                "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("aarch64-linux-android");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.ndk = Some(parse_configure_path(value));
-                }
-                "CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("x86_64-linux-android");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.ndk = Some(parse_configure_path(value));
-                }
-                "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
-                    let path = parse_configure_path(value);
-                    self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]);
-                    self.initial_cargo = push_exe_path(path, &["bin", "cargo"]);
-                }
-                "CFG_PYTHON" if value.len() > 0 => {
-                    let path = parse_configure_path(value);
-                    self.python = Some(path);
-                }
-                "CFG_ENABLE_CCACHE" if value == "1" => {
-                    self.ccache = Some(exe("ccache", &self.build));
-                }
-                "CFG_ENABLE_SCCACHE" if value == "1" => {
-                    self.ccache = Some(exe("sccache", &self.build));
-                }
-                "CFG_CONFIGURE_ARGS" if value.len() > 0 => {
-                    self.configure_args = value.split_whitespace()
-                                               .map(|s| s.to_string())
-                                               .collect();
-                }
-                "CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("arm-unknown-linux-gnueabihf");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.qemu_rootfs = Some(parse_configure_path(value));
-                }
-                "CFG_QEMU_AARCH64_ROOTFS" if value.len() > 0 => {
-                    let target = INTERNER.intern_str("aarch64-unknown-linux-gnu");
-                    let target = self.target_config.entry(target).or_insert(Target::default());
-                    target.qemu_rootfs = Some(parse_configure_path(value));
-                }
-                _ => {}
-            }
-        }
+        config
     }
 
     pub fn verbose(&self) -> bool {
@@ -707,30 +528,6 @@ impl Config {
     }
 }
 
-#[cfg(not(windows))]
-fn parse_configure_path(path: &str) -> PathBuf {
-    path.into()
-}
-
-#[cfg(windows)]
-fn parse_configure_path(path: &str) -> PathBuf {
-    // on windows, configure produces unix style paths e.g. /c/some/path but we
-    // only want real windows paths
-
-    use std::process::Command;
-    use build_helper;
-
-    // '/' is invalid in windows paths, so we can detect unix paths by the presence of it
-    if !path.contains('/') {
-        return path.into();
-    }
-
-    let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path));
-    let win_path = win_path.trim();
-
-    win_path.into()
-}
-
 fn set<T>(field: &mut T, val: Option<T>) {
     if let Some(v) = val {
         *field = v;
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
new file mode 100755
index 00000000000..0e11635c3a0
--- /dev/null
+++ b/src/bootstrap/configure.py
@@ -0,0 +1,408 @@
+#!/usr/bin/env python
+# 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
+
+import sys
+import os
+rust_dir = os.path.dirname(os.path.abspath(__file__))
+rust_dir = os.path.dirname(rust_dir)
+rust_dir = os.path.dirname(rust_dir)
+sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
+import bootstrap
+
+class Option:
+    def __init__(self, name, rustbuild, desc, value):
+        self.name = name
+        self.rustbuild = rustbuild
+        self.desc = desc
+        self.value = value
+
+options = []
+
+def o(*args):
+    options.append(Option(*args, value=False))
+
+def v(*args):
+    options.append(Option(*args, value=True))
+
+o("debug", "rust.debug", "debug mode; disables optimization unless `--enable-optimize` given")
+o("docs", "build.docs", "build standard library documentation")
+o("compiler-docs", "build.compiler-docs", "build compiler documentation")
+o("optimize-tests", "rust.optimize-tests", "build tests with optimizations")
+o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata")
+o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests")
+o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")
+o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds")
+o("local-rust", None, "use an installed rustc rather than downloading a snapshot")
+v("local-rust-root", None, "set prefix for local rust binary")
+o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version")
+o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM")
+o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)")
+o("rpath", "rust.rpath", "build rpaths into rustc itself")
+o("llvm-version-check", "llvm.version-check", "check if the LLVM version is supported, build anyway")
+o("codegen-tests", "rust.codegen-tests", "run the src/test/codegen tests")
+o("option-checking", None, "complain about unrecognized options in this configure script")
+o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)")
+o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date")
+o("vendor", "build.vendor", "enable usage of vendored Rust crates")
+o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, lsan, msan, tsan)")
+o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball")
+o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo")
+o("profiler", "build.profiler", "build the profiler runtime")
+
+# Optimization and debugging options. These may be overridden by the release
+# channel, etc.
+o("optimize", "rust.optimize", "build optimized rust code")
+o("optimize-llvm", "llvm.optimize", "build optimized LLVM")
+o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
+o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
+o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata")
+o("debuginfo", "rust.debuginfo", "build with debugger metadata")
+o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata")
+o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information")
+o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill")
+
+v("prefix", "install.prefix", "set installation prefix")
+v("localstatedir", "install.localstatedir", "local state directory")
+v("datadir", "install.datadir", "install data")
+v("sysconfdir", "install.sysconfdir", "install system configuration files")
+v("infodir", "install.infodir", "install additional info")
+v("libdir", "install.libdir", "install libraries")
+v("mandir", "install.mandir", "install man pages in PATH")
+v("docdir", "install.docdir", "install documentation in PATH")
+v("bindir", "install.bindir", "install binaries")
+
+v("llvm-root", None, "set LLVM root")
+v("python", "build.python", "set path to python")
+v("jemalloc-root", None, "set directory where libjemalloc_pic.a is located")
+v("android-cross-path", "target.arm-linux-androideabi.android-ndk",
+  "Android NDK standalone path (deprecated)")
+v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk",
+  "i686-linux-android NDK standalone path")
+v("arm-linux-androideabi-ndk", "target.arm-linux-androideabi.android-ndk",
+  "arm-linux-androideabi NDK standalone path")
+v("armv7-linux-androideabi-ndk", "target.armv7-linux-androideabi.android-ndk",
+  "armv7-linux-androideabi NDK standalone path")
+v("aarch64-linux-android-ndk", "target.aarch64-linux-android.android-ndk",
+  "aarch64-linux-android NDK standalone path")
+v("x86_64-linux-android-ndk", "target.x86_64-linux-android.android-ndk",
+  "x86_64-linux-android NDK standalone path")
+v("musl-root", "target.x86_64-unknown-linux-musl.musl-root",
+  "MUSL root installation directory (deprecated)")
+v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root",
+  "x86_64-unknown-linux-musl install directory")
+v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root",
+  "i686-unknown-linux-musl install directory")
+v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root",
+  "arm-unknown-linux-musleabi install directory")
+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("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",
+  "rootfs in qemu testing, you probably don't want to use this")
+v("experimental-targets", "llvm.experimental-targets",
+  "experimental LLVM targets to build")
+v("release-channel", "rust.channel", "the name of the release channel to build")
+
+# Used on systems where "cc" and "ar" are unavailable
+v("default-linker", "rust.default-linker", "the default linker")
+v("default-ar", "rust.default-ar", "the default ar")
+
+# Many of these are saved below during the "writing configuration" step
+# (others are conditionally saved).
+o("manage-submodules", "build.submodules", "let the build manage the git submodules")
+o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc")
+o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two")
+o("extended", "build.extended", "build an extended rust tool set")
+
+v("build", "build.build", "GNUs ./configure syntax LLVM build triple")
+v("host", None, "GNUs ./configure syntax LLVM host triples")
+v("target", None, "GNUs ./configure syntax LLVM target triples")
+
+v("set", None, "set arbitrary key/value pairs in TOML configuration")
+
+def p(msg):
+    print("configure: " + msg)
+
+def err(msg):
+    print("configure: error: " + msg)
+    sys.exit(1)
+
+if '--help' in sys.argv or '-h' in sys.argv:
+    print('Usage: ./configure [options]')
+    print('')
+    print('Options')
+    for option in options:
+        if 'android' in option.name:
+            # no one needs to know about these obscure options
+            continue
+        if option.value:
+            print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc))
+        else:
+            print('\t{:30} {}'.format('--enable-{}'.format(option.name), option.desc))
+    print('')
+    print('This configure script is a thin configuration shim over the true')
+    print('configuration system, `config.toml`. You can explore the comments')
+    print('in `config.toml.example` next to this configure script to see')
+    print('more information about what each option is. Additionally you can')
+    print('pass `--set` as an argument to set arbitrary key/value pairs')
+    print('in the TOML configuration if desired')
+    print('')
+    print('Also note that all options which take `--enable` can similarly')
+    print('be passed with `--disable-foo` to forcibly disable the option')
+    sys.exit(0)
+
+# Parse all command line arguments into one of these three lists, handling
+# boolean and value-based options separately
+unknown_args = []
+need_value_args = []
+known_args = {}
+
+p("processing command line")
+i = 1
+while i < len(sys.argv):
+    arg = sys.argv[i]
+    i += 1
+    if not arg.startswith('--'):
+        unknown_args.append(arg)
+        continue
+
+    found = False
+    for option in options:
+        value = None
+        if option.value:
+            keyval = arg[2:].split('=', 1)
+            key = keyval[0]
+            if option.name != key:
+                continue
+
+            if len(keyval) > 1:
+                value = keyval[1]
+            elif i < len(sys.argv):
+                value = sys.argv[i]
+                i += 1
+            else:
+                need_value_args.append(arg)
+                continue
+        else:
+            if arg[2:] == 'enable-' + option.name:
+                value = True
+            elif arg[2:] == 'disable-' + option.name:
+                value = False
+            else:
+                continue
+
+        found = True
+        if not option.name in known_args:
+            known_args[option.name] = []
+        known_args[option.name].append((option, value))
+        break
+
+    if not found:
+        unknown_args.append(arg)
+p("")
+
+if 'option-checking' not in known_args or known_args['option-checking'][1]:
+    if len(unknown_args) > 0:
+        err("Option '" + unknown_args[0] + "' is not recognized")
+    if len(need_value_args) > 0:
+        err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0]))
+
+# Parse all known arguments into a configuration structure that reflects the
+# TOML we're going to write out
+config = {}
+
+def build():
+    if 'build' in known_args:
+        return known_args['build'][0][1]
+    return bootstrap.default_build_triple()
+
+def set(key, value):
+      s = "{:20} := {}".format(key, value)
+      if len(s) < 70:
+          p(s)
+      else:
+          p(s[:70] + " ...")
+
+      arr = config
+      parts = key.split('.')
+      for i, part in enumerate(parts):
+          if i == len(parts) - 1:
+              arr[part] = value
+          else:
+              if not part in arr:
+                  arr[part] = {}
+              arr = arr[part]
+
+for key in known_args:
+    # The `set` option is special and an be passed a bunch of times
+    if key == 'set':
+        for option, value in known_args[key]:
+            keyval = value.split('=', 1)
+            set(keyval[0], True if len(keyval) == 1 else keyval[1])
+        continue
+
+    # Ensure each option is only passed once
+    arr = known_args[key]
+    if len(arr) > 1:
+        err("Option '{}' provided more than once".format(key))
+    option, value = arr[0]
+
+    # If we have a clear avenue to set our value in rustbuild, do so
+    if option.rustbuild is not None:
+        set(option.rustbuild, value)
+        continue
+
+    # Otherwise we're a "special" option and need some extra handling, so do
+    # that here.
+    if option.name == 'sccache':
+        set('llvm.ccache', 'sccache')
+    elif option.name == 'local-rust':
+        for path in os.environ['PATH'].split(os.pathsep):
+            if os.path.exists(path + '/rustc'):
+                set('build.rustc', path + '/rustc')
+                break
+        for path in os.environ['PATH'].split(os.pathsep):
+            if os.path.exists(path + '/cargo'):
+                set('build.cargo', path + '/cargo')
+                break
+    elif option.name == 'local-rust-root':
+        set('build.rustc', value + '/bin/rustc')
+        set('build.cargo', value + '/bin/cargo')
+    elif option.name == 'llvm-root':
+        set('target.{}.llvm-config'.format(build()), value + '/bin/llvm-config')
+    elif option.name == 'jemalloc-root':
+        set('target.{}.jemalloc'.format(build()), value + '/libjemalloc_pic.a')
+    elif option.name == 'host':
+        set('build.host', value.split(','))
+    elif option.name == 'target':
+        set('build.target', value.split(','))
+    elif option.name == 'option-checking':
+        # this was handled above
+        pass
+    else:
+        raise RuntimeError("unhandled option {}".format(option.name))
+
+set('build.configure-args', sys.argv[1:])
+
+# "Parse" the `config.toml.example` file into the various sections, and we'll
+# use this as a template of a `config.toml` to write out which preserves
+# all the various comments and whatnot.
+#
+# Note that the `target` section is handled separately as we'll duplicate it
+# per configure dtarget, so there's a bit of special handling for that here.
+sections = {}
+cur_section = None
+sections[None] = []
+section_order = [None]
+targets = {}
+
+for line in open(rust_dir + '/config.toml.example').read().split("\n"):
+    if line.startswith('['):
+        cur_section = line[1:-1]
+        if cur_section.startswith('target'):
+            cur_section = 'target'
+        elif '.' in cur_section:
+            raise RuntimeError("don't know how to deal with section: {}".format(cur_section))
+        sections[cur_section] = [line]
+        section_order.append(cur_section)
+    else:
+        sections[cur_section].append(line)
+
+# Fill out the `targets` array by giving all configured targets a copy of the
+# `target` section we just loaded from the example config
+configured_targets = [build()]
+if 'build' in config:
+    if 'host' in config['build']:
+        configured_targets += config['build']['host']
+    if 'target' in config['build']:
+        configured_targets += config['build']['target']
+if 'target' in config:
+    for target in config['target']:
+        configured_targets.append(target)
+for target in configured_targets:
+    targets[target] = sections['target'][:]
+    targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", target)
+
+# Here we walk through the constructed configuration we have from the parsed
+# command line arguemnts. We then apply each piece of configuration by
+# basically just doing a `sed` to change the various configuration line to what
+# we've got configure.
+def to_toml(value):
+    if isinstance(value, bool):
+        if value:
+            return "true"
+        else:
+            return "false"
+    elif isinstance(value, list):
+        return '[' + ', '.join(map(to_toml, value)) + ']'
+    elif isinstance(value, str):
+        return "'" + value + "'"
+    else:
+        raise 'no toml'
+
+def configure_section(lines, config):
+    for key in config:
+        value = config[key]
+        found = False
+        for i, line in enumerate(lines):
+            if not line.startswith('#' + key + ' = '):
+                continue
+            found = True
+            lines[i] = "{} = {}".format(key, to_toml(value))
+            break
+        if not found:
+            raise RuntimeError("failed to find config line for {}".format(key))
+
+for section_key in config:
+    section_config = config[section_key]
+    if not section_key in sections:
+        raise RuntimeError("config key {} not in sections".format(key))
+
+    if section_key == 'target':
+        for target in section_config:
+            configure_section(targets[target], section_config[target])
+    else:
+        configure_section(sections[section_key], section_config)
+
+# Now that we've built up our `config.toml`, write it all out in the same
+# order that we read it in.
+p("")
+p("writing `config.toml` in current directory")
+with open('config.toml', 'w') as f:
+    for section in section_order:
+        if section == 'target':
+            for target in targets:
+                for line in targets[target]:
+                    f.write(line + "\n")
+        else:
+            for line in sections[section]:
+                f.write(line + "\n")
+
+with open('Makefile', 'w') as f:
+    contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in')
+    contents = open(contents).read()
+    contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/')
+    contents = contents.replace("$(CFG_PYTHON)", sys.executable)
+    f.write(contents)
+
+# Finally, clean up with a bit of a help message
+relpath = os.path.dirname(__file__)
+if relpath == '':
+    relpath = '.'
+
+p("")
+p("run `python {}/x.py --help`".format(relpath))
+p("")
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index bfcfb5f9a37..153ffe509f3 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -822,6 +822,7 @@ impl Step for PlainSourceTarball {
             "RELEASES.md",
             "configure",
             "x.py",
+            "config.toml.example",
         ];
         let src_dirs = [
             "man",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 05c7d689f2c..86f5346bea1 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -213,13 +213,13 @@ impl Step for TheBook {
         let name = self.name;
         // build book first edition
         builder.ensure(Rustbook {
-            target: target,
+            target,
             name: INTERNER.intern_string(format!("{}/first-edition", name)),
         });
 
         // build book second edition
         builder.ensure(Rustbook {
-            target: target,
+            target,
             name: INTERNER.intern_string(format!("{}/second-edition", name)),
         });
 
@@ -240,6 +240,51 @@ impl Step for TheBook {
     }
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct CargoBook {
+    target: Interned<String>,
+}
+
+impl Step for CargoBook {
+    type Output = ();
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        let builder = run.builder;
+        run.path("src/doc/cargo").default_condition(builder.build.config.docs)
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(CargoBook {
+            target: run.target,
+        });
+    }
+
+    /// Create a placeholder for the cargo documentation so that doc.rust-lang.org/cargo will
+    /// redirect to doc.crates.io. We want to publish doc.rust-lang.org/cargo in the paper
+    /// version of the book, but we don't want to rush the process of switching cargo's docs
+    /// over to mdbook and deploying them. When the cargo book is ready, this implementation
+    /// should build the mdbook instead of this redirect page.
+    fn run(self, builder: &Builder) {
+        let build = builder.build;
+        let out = build.doc_out(self.target);
+
+        let cargo_dir = out.join("cargo");
+        t!(fs::create_dir_all(&cargo_dir));
+
+        let index = cargo_dir.join("index.html");
+        let redirect_html = r#"
+            <html>
+                <head>
+                    <meta http-equiv="refresh" content="0; URL='http://doc.crates.io'" />
+                </head>
+            </html>"#;
+
+        println!("Creating cargo book redirect page");
+        t!(t!(File::create(&index)).write_all(redirect_html.as_bytes()));
+    }
+}
+
 fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String>, markdown: &str) {
     let build = builder.build;
     let out = build.doc_out(target);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index a9cefb65f49..a84d43d3dee 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -274,14 +274,14 @@ Arguments:
             }
             "test" => {
                 Subcommand::Test {
-                    paths: paths,
+                    paths,
                     test_args: matches.opt_strs("test-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
                 }
             }
             "bench" => {
                 Subcommand::Bench {
-                    paths: paths,
+                    paths,
                     test_args: matches.opt_strs("test-args"),
                 }
             }
@@ -297,12 +297,12 @@ Arguments:
             }
             "dist" => {
                 Subcommand::Dist {
-                    paths: paths,
+                    paths,
                 }
             }
             "install" => {
                 Subcommand::Install {
-                    paths: paths,
+                    paths,
                 }
             }
             _ => {
@@ -324,7 +324,7 @@ Arguments:
 
         Flags {
             verbose: matches.opt_count("verbose"),
-            stage: stage,
+            stage,
             on_fail: matches.opt_str("on-fail"),
             keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()),
             build: matches.opt_str("build").map(|s| INTERNER.intern_string(s)),
@@ -333,9 +333,9 @@ Arguments:
             target: split(matches.opt_strs("target"))
                 .into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(),
             config: cfg_file,
-            src: src,
+            src,
             jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
-            cmd: cmd,
+            cmd,
             incremental: matches.opt_present("incremental"),
         }
     }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 1452a38f6ed..55358f2ffcb 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -314,19 +314,19 @@ impl Build {
             hosts: config.hosts.clone(),
             targets: config.targets.clone(),
 
-            config: config,
-            src: src,
-            out: out,
+            config,
+            src,
+            out,
 
-            rust_info: rust_info,
-            cargo_info: cargo_info,
-            rls_info: rls_info,
+            rust_info,
+            cargo_info,
+            rls_info,
             cc: HashMap::new(),
             cxx: HashMap::new(),
             crates: HashMap::new(),
             lldb_version: None,
             lldb_python_dir: None,
-            is_sudo: is_sudo,
+            is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: Cell::new(0),
         }
@@ -444,7 +444,7 @@ impl Build {
     }
 
     /// Returns the root output directory for all Cargo output in a given stage,
-    /// running a particular compiler, wehther or not we're building the
+    /// running a particular compiler, whether or not we're building the
     /// standard library, and targeting the specified architecture.
     fn cargo_out(&self,
                  compiler: Compiler,
@@ -656,6 +656,16 @@ impl Build {
         base
     }
 
+    /// Returns if this target should statically link the C runtime, if specified
+    fn crt_static(&self, target: Interned<String>) -> Option<bool> {
+        if target.contains("pc-windows-msvc") {
+            Some(true)
+        } else {
+            self.config.target_config.get(&target)
+                .and_then(|t| t.crt_static)
+        }
+    }
+
     /// Returns the "musl root" for this `target`, if defined
     fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
         self.config.target_config.get(&target)
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index ad555be877a..5f1df1d26e2 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -75,10 +75,10 @@ fn build_krate(build: &mut Build, krate: &str) {
                 doc_step: format!("doc-crate-{}", name),
                 test_step: format!("test-crate-{}", name),
                 bench_step: format!("bench-crate-{}", name),
-                name: name,
+                name,
                 version: package.version,
                 deps: Vec::new(),
-                path: path,
+                path,
             });
         }
     }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 9410927824c..67495b891f8 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -8,8 +8,6 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
-include config.mk
-
 ifdef VERBOSE
 Q :=
 BOOTSTRAP_ARGS := -v
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 59efbd5c4d2..0a307e72bf6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -11,7 +11,7 @@
 //! Compilation of native dependencies like LLVM.
 //!
 //! Native projects like LLVM unfortunately aren't suited just yet for
-//! compilation in build scripts that Cargo has. This is because thie
+//! compilation in build scripts that Cargo has. This is because the
 //! compilation takes a *very* long time but also because we don't want to
 //! compile LLVM 3 times as part of a normal bootstrap (we want it cached).
 //!
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 436a13500f2..54208d8bb57 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -93,10 +93,27 @@ pub fn check(build: &mut Build) {
     }
 
     // Ninja is currently only used for LLVM itself.
-    // Some Linux distros rename `ninja` to `ninja-build`.
-    // CMake can work with either binary name.
-    if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() {
-        cmd_finder.must_have("ninja");
+    if building_llvm {
+        if build.config.ninja {
+            // Some Linux distros rename `ninja` to `ninja-build`.
+            // CMake can work with either binary name.
+            if cmd_finder.maybe_have("ninja-build").is_none() {
+                cmd_finder.must_have("ninja");
+            }
+        }
+
+        // If ninja isn't enabled but we're building for MSVC then we try
+        // doubly hard to enable it. It was realized in #43767 that the msbuild
+        // CMake generator for MSVC doesn't respect configuration options like
+        // disabling LLVM assertions, which can often be quite important!
+        //
+        // In these cases we automatically enable Ninja if we find it in the
+        // environment.
+        if !build.config.ninja && build.config.build.contains("msvc") {
+            if cmd_finder.maybe_have("ninja").is_some() {
+                build.config.ninja = true;
+            }
+        }
     }
 
     build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
@@ -151,8 +168,15 @@ pub fn check(build: &mut Build) {
             panic!("the iOS target is only supported on macOS");
         }
 
-        // Make sure musl-root is valid if specified
+        // Make sure musl-root is valid
         if target.contains("musl") && !target.contains("mips") {
+            // If this is a native target (host is also musl) and no musl-root is given,
+            // fall back to the system toolchain in /usr before giving up
+            if build.musl_root(*target).is_none() && build.config.build == *target {
+                let target = build.config.target_config.entry(target.clone())
+                                 .or_insert(Default::default());
+                target.musl_root = Some("/usr".into());
+            }
             match build.musl_root(*target) {
                 Some(root) => {
                     if fs::metadata(root.join("lib/libc.a")).is_err() {
diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile
index 6cdaf6acfef..49d07d28d3c 100644
--- a/src/ci/docker/arm-android/Dockerfile
+++ b/src/ci/docker/arm-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
     download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9
@@ -38,4 +35,4 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 COPY scripts/android-start-emulator.sh /scripts/
-ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"]
+ENTRYPOINT ["/scripts/android-start-emulator.sh"]
diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile
index 14785b706fb..191f8e3a289 100644
--- a/src/ci/docker/armhf-gnu/Dockerfile
+++ b/src/ci/docker/armhf-gnu/Dockerfile
@@ -73,14 +73,9 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
 # TODO: What is this?!
 RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS \
       --target=arm-unknown-linux-gnueabihf \
       --qemu-armhf-rootfs=/tmp/rootfs
diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile
index 1c39e8523da..28caf1fb57a 100644
--- a/src/ci/docker/asmjs/Dockerfile
+++ b/src/ci/docker/asmjs/Dockerfile
@@ -13,9 +13,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/emscripten.sh /scripts/
 RUN bash /scripts/emscripten.sh
 
@@ -35,5 +32,3 @@ ENV SCRIPT python2.7 ../x.py test --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile
index 70dfbb53da2..a83bbe9c60e 100644
--- a/src/ci/docker/cross/Dockerfile
+++ b/src/ci/docker/cross/Dockerfile
@@ -21,9 +21,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 WORKDIR /tmp
 
 COPY cross/build-rumprun.sh /tmp/
@@ -38,6 +35,9 @@ RUN ./install-mips-musl.sh
 COPY cross/install-mipsel-musl.sh /tmp/
 RUN ./install-mipsel-musl.sh
 
+COPY cross/install-x86_64-redox.sh /tmp/
+RUN ./install-x86_64-redox.sh
+
 ENV TARGETS=asmjs-unknown-emscripten
 ENV TARGETS=$TARGETS,wasm32-unknown-emscripten
 ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd
@@ -47,10 +47,12 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
 ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
+ENV TARGETS=$TARGETS,x86_64-unknown-redox
 
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
-    CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc
+    CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \
+    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc
 
 # Suppress some warnings in the openwrt toolchains we downloaded
 ENV STAGING_DIR=/tmp
@@ -66,5 +68,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
 # sccache
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/scripts/dumb-init.sh b/src/ci/docker/cross/install-x86_64-redox.sh
index 42ecec6ba08..8e052c4acd2 100644..100755
--- a/src/ci/docker/scripts/dumb-init.sh
+++ b/src/ci/docker/cross/install-x86_64-redox.sh
@@ -1,3 +1,4 @@
+#!/bin/bash
 # 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,8 +9,15 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+# ignore-tidy-linelength
+
 set -ex
 
-curl -fOL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb
-dpkg -i dumb-init_*.deb
-rm dumb-init_*.deb
+apt-get update
+apt-get install -y --no-install-recommends software-properties-common apt-transport-https
+
+apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F
+add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /'
+
+apt-get update
+apt-get install -y x86-64-unknown-redox-gcc
diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
index e468b1abdfb..9a0e4531223 100644
--- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile
+++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile
@@ -70,14 +70,9 @@ RUN chmod +x rootfs/etc/init.d/rcS
 COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c
 RUN aarch64-linux-gnu-gcc addentropy.c -o rootfs/addentropy -static
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS \
       --target=aarch64-unknown-linux-gnu \
       --qemu-aarch64-rootfs=/tmp/rootfs
diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
index 1c9e036f093..20d823a3d73 100644
--- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
     download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21
@@ -28,5 +25,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile
index 326e00548b1..3435d641a13 100644
--- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
     download_ndk android-ndk-r13b-linux-x86_64.zip && \
@@ -46,5 +43,3 @@ ENV SCRIPT \
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile
index d01648e2b9d..4bb7053760f 100644
--- a/src/ci/docker/disabled/dist-i686-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
     download_ndk android-ndk-r13b-linux-x86_64.zip && \
@@ -46,5 +43,3 @@ ENV SCRIPT \
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
index 2622b4b3fac..525b218417b 100644
--- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
+++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
     download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21
@@ -28,5 +25,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
new file mode 100644
index 00000000000..ed19939545f
--- /dev/null
+++ b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile
@@ -0,0 +1,22 @@
+FROM ubuntu:16.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
+
+WORKDIR /tmp
+COPY cross/install-x86_64-redox.sh /tmp/
+RUN ./install-x86_64-redox.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV \
+    AR_x86_64_unknown_redox=x86_64-unknown-redox-ar \
+    CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
+    CXX_x86_64_unknown_redox=x86_64-unknown-redox-g++
+
+ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-redox --enable-extended
+ENV SCRIPT python2.7 ../x.py dist --target x86_64-unknown-redox
diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile
index 4e337883165..6323369421b 100644
--- a/src/ci/docker/disabled/wasm32-exp/Dockerfile
+++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile
@@ -15,10 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   jq \
   bzip2
 
-# dumb-init
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 # emscripten
 COPY scripts/emscripten-wasm.sh /scripts/
 COPY disabled/wasm32-exp/node.sh /usr/local/bin/node
@@ -37,6 +33,3 @@ ENV TARGETS=wasm32-experimental-emscripten
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly
 
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
-
-# init
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile
index bf9bf77e649..7f6f8ae0882 100644
--- a/src/ci/docker/disabled/wasm32/Dockerfile
+++ b/src/ci/docker/disabled/wasm32/Dockerfile
@@ -13,9 +13,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 # emscripten
 COPY scripts/emscripten.sh /scripts/
 RUN bash /scripts/emscripten.sh
@@ -36,5 +33,3 @@ ENV TARGETS=wasm32-unknown-emscripten
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS
 
 ENV SCRIPT python2.7 ../x.py test --target $TARGETS
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile
index cc3b6b8c692..841d3012125 100644
--- a/src/ci/docker/dist-aarch64-linux/Dockerfile
+++ b/src/ci/docker/dist-aarch64-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile
index f3beddfae0a..a36f7fc1ac5 100644
--- a/src/ci/docker/dist-android/Dockerfile
+++ b/src/ci/docker/dist-android/Dockerfile
@@ -3,9 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/android-base-apt-get.sh /scripts/
 RUN sh /scripts/android-base-apt-get.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 # ndk
 COPY scripts/android-ndk.sh /scripts/
 RUN . /scripts/android-ndk.sh && \
@@ -36,5 +33,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile
index 590d6eb98b3..ecd5090ea05 100644
--- a/src/ci/docker/dist-arm-linux/Dockerfile
+++ b/src/ci/docker/dist-arm-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile
index b3dedc4b7f0..5bbd17bd414 100644
--- a/src/ci/docker/dist-armhf-linux/Dockerfile
+++ b/src/ci/docker/dist-armhf-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile
index 82536b68bbe..ea9034d7178 100644
--- a/src/ci/docker/dist-armv7-linux/Dockerfile
+++ b/src/ci/docker/dist-armv7-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile
index 24ad12a4900..e18cb453baf 100644
--- a/src/ci/docker/dist-fuchsia/Dockerfile
+++ b/src/ci/docker/dist-fuchsia/Dockerfile
@@ -24,11 +24,6 @@ WORKDIR /tmp
 COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/
 RUN /tmp/build-toolchain.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
index 036dce2a735..efde3ff5296 100644
--- a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
+++ b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
@@ -20,11 +20,6 @@ WORKDIR /build/
 COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/
 RUN sh /build/build-musl.sh && rm -rf /build
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile
index c40881332a1..b82d227b3ef 100644
--- a/src/ci/docker/dist-i686-freebsd/Dockerfile
+++ b/src/ci/docker/dist-i686-freebsd/Dockerfile
@@ -19,11 +19,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY dist-i686-freebsd/build-toolchain.sh /tmp/
 RUN /tmp/build-toolchain.sh i686
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile
index beb53783bac..a5d776af19d 100644
--- a/src/ci/docker/dist-i686-linux/Dockerfile
+++ b/src/ci/docker/dist-i686-linux/Dockerfile
@@ -76,11 +76,6 @@ RUN ./build-cmake.sh
 COPY dist-i686-linux/build-headers.sh /tmp/
 RUN ./build-headers.sh
 
-RUN curl -Lo /rustroot/dumb-init \
-      https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \
-      chmod +x /rustroot/dumb-init
-ENTRYPOINT ["/rustroot/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile
index 81997e0508a..94a3cf8a382 100644
--- a/src/ci/docker/dist-mips-linux/Dockerfile
+++ b/src/ci/docker/dist-mips-linux/Dockerfile
@@ -17,14 +17,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV HOSTS=mips-unknown-linux-gnu
 
 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile
index 646cb4d256a..0b0dfff1fe3 100644
--- a/src/ci/docker/dist-mips64-linux/Dockerfile
+++ b/src/ci/docker/dist-mips64-linux/Dockerfile
@@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV HOSTS=mips64-unknown-linux-gnuabi64
 
 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile
index 1abb04fd8b2..1810b1cdc5a 100644
--- a/src/ci/docker/dist-mips64el-linux/Dockerfile
+++ b/src/ci/docker/dist-mips64el-linux/Dockerfile
@@ -17,14 +17,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV HOSTS=mips64el-unknown-linux-gnuabi64
 
 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile
index a78e39e7d71..f5be0748475 100644
--- a/src/ci/docker/dist-mipsel-linux/Dockerfile
+++ b/src/ci/docker/dist-mipsel-linux/Dockerfile
@@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV HOSTS=mipsel-unknown-linux-gnu
 
 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile
index ed9f883cc83..14ce3654fce 100644
--- a/src/ci/docker/dist-powerpc-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile
index 523211498fb..1f6e83e2f49 100644
--- a/src/ci/docker/dist-powerpc64-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile
@@ -3,10 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile
index 06b262c515a..d4677e18060 100644
--- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile
+++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile
index 84769af12b5..39478e92f7c 100644
--- a/src/ci/docker/dist-s390x-linux/Dockerfile
+++ b/src/ci/docker/dist-s390x-linux/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
index b62b46701a7..b7c00df4db2 100644
--- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile
@@ -19,11 +19,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/
 RUN /tmp/build-toolchain.sh x86_64
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile
index d0ab47ad3dc..a954fd86a24 100644
--- a/src/ci/docker/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/dist-x86_64-linux/Dockerfile
@@ -76,11 +76,6 @@ RUN ./build-cmake.sh
 COPY dist-x86_64-linux/build-headers.sh /tmp/
 RUN ./build-headers.sh
 
-RUN curl -Lo /rustroot/dumb-init \
-      https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \
-      chmod +x /rustroot/dumb-init
-ENTRYPOINT ["/rustroot/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile
index eebc283e966..91ed6bfe1f6 100644
--- a/src/ci/docker/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/dist-x86_64-musl/Dockerfile
@@ -20,11 +20,6 @@ WORKDIR /build/
 COPY dist-x86_64-musl/build-musl.sh /build/
 RUN sh /build/build-musl.sh && rm -rf /build
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile
index 0c140500266..4fd2503c31b 100644
--- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile
+++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile
@@ -3,11 +3,6 @@ FROM ubuntu:16.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 # Ubuntu 16.04 (this container) ships with make 4, but something in the
 # toolchains we build below chokes on that, so go back to make 3
 COPY scripts/make3.sh /scripts/
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 56ff9922ae3..5a83bd318c4 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 1c1333cd7c8..daa24e0e818 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 ENV SCRIPT python2.7 ../x.py test
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index d3f339bc15f..5eba81ff60a 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -89,6 +89,7 @@ exec docker \
   --env TRAVIS_BRANCH \
   --volume "$HOME/.cargo:/cargo" \
   --volume "$HOME/rustsrc:$HOME/rustsrc" \
+  --init \
   --rm \
   rust-ci \
   /checkout/src/ci/run.sh
diff --git a/src/ci/docker/x86_64-gnu-aux/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile
index a449526efcc..35a387221c6 100644
--- a/src/ci/docker/x86_64-gnu-aux/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile
@@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils \
   pkg-config
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check-aux
diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile
index 8111118ad3d..95d41028595 100644
--- a/src/ci/docker/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile
@@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-debug \
diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile
index c3fe8ea51cb..786f59eb9f7 100644
--- a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile
@@ -15,14 +15,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV SCRIPT python2.7 ../x.py test distcheck
 ENV DIST_SRC 1
diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
index 377e0869557..70390c2ac1d 100644
--- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
@@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-full-bootstrap
diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile
index a21a99e965e..d323677698c 100644
--- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile
@@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache
 ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
index 1a9f1d2d737..e832a2445ba 100644
--- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
@@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-3.7
diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile
index e008b21f66f..d2b0dd13dc2 100644
--- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile
@@ -13,13 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile
index 3a6760b4762..7570bca5906 100644
--- a/src/ci/docker/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/x86_64-gnu/Dockerfile
@@ -13,13 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   gdb \
   xz-utils
 
-COPY scripts/dumb-init.sh /scripts/
-RUN sh /scripts/dumb-init.sh
-
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-ENTRYPOINT ["/usr/bin/dumb-init", "--"]
-
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler
 ENV SCRIPT python2.7 ../x.py test
diff --git a/src/doc/book b/src/doc/book
-Subproject 6f1a03dae6bcea44976918186f2d554186b3499
+Subproject d09c9e8144ed32170b7596abb145ade8b097aca
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject f570bcb681771d691aa4fdb8dfcfad1939844bf
+Subproject a4322ccb289a43cc238d4536982f184a3eec9ba
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 1abfbaa70313fdf527cf799ffd9b9a096a62105
+Subproject 266d429a48468371d2d90669f6a30dd659bb4bd
diff --git a/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md b/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md
deleted file mode 100644
index 2583d350ebe..00000000000
--- a/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# `rvalue_static_promotion`
-
-The tracking issue for this feature is: [#38865]
-
-[#38865]: https://github.com/rust-lang/rust/issues/38865
-
-------------------------
-
-The `rvalue_static_promotion` feature allows directly creating `'static` references to
-constant `rvalue`s, which in particular allowing for more concise code in the common case
-in which a `'static` reference is all that's needed.
-
-
-## Examples
-
-```rust
-#![feature(rvalue_static_promotion)]
-
-fn main() {
-    let DEFAULT_VALUE: &'static u32 = &42;
-    assert_eq!(*DEFAULT_VALUE, 42);
-}
-```
diff --git a/src/doc/unstable-book/src/library-features/string-retain.md b/src/doc/unstable-book/src/library-features/string-retain.md
new file mode 100644
index 00000000000..049444aa49b
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/string-retain.md
@@ -0,0 +1,23 @@
+# `string_retain`
+
+The tracking issue for this feature is: [#43874]
+
+[#43874]: https://github.com/rust-lang/rust/issues/43874
+
+------------------------
+
+Retains only the characters specified by the predicate.
+
+In other words, remove all characters `c` such that `f(c)` returns `false`.
+This method operates in place and preserves the order of the retained
+characters.
+
+```rust
+#![feature(string_retain)]
+
+let mut s = String::from("f_o_ob_ar");
+
+s.retain(|c| c != '_');
+
+assert_eq!(s, "foobar");
+```
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index a5449b748dd..7e8fde20346 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -29,7 +29,7 @@ showing the expected renderings.
 
 In order to avoid one-off dependencies for this task, this script uses
 a reasonably working HTML parser and the existing XPath implementation
-from Python 2's standard library. Hopefully we won't render
+from Python's standard library. Hopefully we won't render
 non-well-formed HTML.
 
 # Commands
@@ -110,11 +110,17 @@ import os.path
 import re
 import shlex
 from collections import namedtuple
-from HTMLParser import HTMLParser
+try:
+    from html.parser import HTMLParser
+except ImportError:
+    from HTMLParser import HTMLParser
 from xml.etree import cElementTree as ET
 
 # &larrb;/&rarrb; are not in HTML 4 but are in HTML 5
-from htmlentitydefs import entitydefs
+try:
+    from html.entities import entitydefs
+except ImportError:
+    from htmlentitydefs import entitydefs
 entitydefs['larrb'] = u'\u21e4'
 entitydefs['rarrb'] = u'\u21e5'
 entitydefs['nbsp'] = ' '
@@ -123,6 +129,11 @@ entitydefs['nbsp'] = ' '
 VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
                      'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
 
+# Python 2 -> 3 compatibility
+try:
+    unichr
+except NameError:
+    unichr = chr
 
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
@@ -184,12 +195,8 @@ def concat_multi_lines(f):
 
         # strip the common prefix from the current line if needed
         if lastline is not None:
-            maxprefix = 0
-            for i in xrange(min(len(line), len(lastline))):
-                if line[i] != lastline[i]:
-                    break
-                maxprefix += 1
-            line = line[maxprefix:].lstrip()
+            common_prefix = os.path.commonprefix([line, lastline])
+            line = line[len(common_prefix):].lstrip()
 
         firstlineno = firstlineno or lineno
         if line.endswith('\\'):
@@ -213,7 +220,7 @@ LINE_PATTERN = re.compile(r'''
 
 
 def get_commands(template):
-    with open(template, 'rUb') as f:
+    with open(template, 'rU') as f:
         for lineno, line in concat_multi_lines(f):
             m = LINE_PATTERN.search(line)
             if not m:
@@ -372,7 +379,7 @@ def check_command(c, cache):
                     cache.get_file(c.args[0])
                     ret = True
                 except FailedCheck as err:
-                    cerr = err.message
+                    cerr = str(err)
                     ret = False
             elif len(c.args) == 2: # @has/matches <path> <pat> = string test
                 cerr = "`PATTERN` did not match"
@@ -413,9 +420,9 @@ def check_command(c, cache):
 
     except FailedCheck as err:
         message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd)
-        print_err(c.lineno, c.context, err.message, message)
+        print_err(c.lineno, c.context, str(err), message)
     except InvalidCheck as err:
-        print_err(c.lineno, c.context, err.message)
+        print_err(c.lineno, c.context, str(err))
 
 def check(target, commands):
     cache = CachedFiles(target)
diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json
index c70791be030..d615037b632 100644
--- a/src/etc/platform-intrinsics/powerpc.json
+++ b/src/etc/platform-intrinsics/powerpc.json
@@ -121,6 +121,41 @@
             "llvm": "vavg{0.kind}{0.data_type_short}",
             "ret": "i(8-32)",
             "args": ["0", "0"]
+        },
+        {
+            "intrinsic": "packs{0.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vpk{0.kind}{1.data_type_short}{0.kind}s",
+            "ret": "i(8-16)",
+            "args": ["0W", "1"]
+        },
+        {
+            "intrinsic": "packsu{1.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vpk{1.kind}{1.data_type_short}{0.kind}s",
+            "ret": "u(8-16)",
+            "args": ["0Ws", "1"]
+        },
+        {
+            "intrinsic": "packpx",
+            "width": [128],
+            "llvm": "vpkpx",
+            "ret": "s16",
+            "args": ["s32", "s32"]
+        },
+        {
+            "intrinsic": "unpackl{1.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vupkl{1.kind}{1.data_type_short}",
+            "ret": "s(16-32)",
+            "args": ["0N"]
+        },
+        {
+            "intrinsic": "unpackh{1.kind}{1.data_type_short}",
+            "width": [128],
+            "llvm": "vupkh{1.kind}{1.data_type_short}",
+            "ret": "s(16-32)",
+            "args": ["0N"]
         }
     ]
 }
diff --git a/src/jemalloc b/src/jemalloc
-Subproject 11bfb0dcf85f7aa92abd30524bb1e42e18d108c
+Subproject 1f5a28755e301ac581e2048011e4e0ff3da482e
diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs
index 2b3df15f716..f14f2702324 100644
--- a/src/liballoc/allocator.rs
+++ b/src/liballoc/allocator.rs
@@ -110,7 +110,7 @@ impl Layout {
 
     /// Creates a layout, bypassing all checks.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe as it does not verify that `align` is
     /// a power-of-two that is also less than or equal to 2^31, nor
@@ -293,7 +293,7 @@ impl Layout {
     /// Creates a layout describing the record for `self` followed by
     /// `next` with no additional padding between the two. Since no
     /// padding is inserted, the alignment of `next` is irrelevant,
-    /// and is not incoporated *at all* into the resulting layout.
+    /// and is not incorporated *at all* into the resulting layout.
     ///
     /// Returns `(k, offset)`, where `k` is layout of the concatenated
     /// record and `offset` is the relative location, in bytes, of the
@@ -485,7 +485,7 @@ pub unsafe trait Alloc {
     /// behavior, e.g. to ensure initialization to particular sets of
     /// bit patterns.)
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure that `layout` has non-zero size.
@@ -513,7 +513,7 @@ pub unsafe trait Alloc {
 
     /// Deallocate the memory referenced by `ptr`.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -528,7 +528,7 @@ pub unsafe trait Alloc {
     ///   to allocate that block of memory.
     unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout);
 
-    /// Allocator-specific method for signalling an out-of-memory
+    /// Allocator-specific method for signaling an out-of-memory
     /// condition.
     ///
     /// `oom` aborts the thread or process, optionally performing
@@ -539,7 +539,7 @@ pub unsafe trait Alloc {
     /// unsatisfied allocation request (signaled by an error such as
     /// `AllocErr::Exhausted`), and wish to abandon computation rather
     /// than attempt to recover locally. Such clients should pass the
-    /// signalling error value back into `oom`, where the allocator
+    /// signaling error value back into `oom`, where the allocator
     /// may incorporate that error value into its diagnostic report
     /// before aborting.
     ///
@@ -617,7 +617,7 @@ pub unsafe trait Alloc {
     /// behavior is well-defined (though underspecified) when this
     /// constraint is violated; further discussion below.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -688,7 +688,7 @@ pub unsafe trait Alloc {
     /// Behaves like `alloc`, but also ensures that the contents
     /// are set to zero before being returned.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -714,7 +714,7 @@ pub unsafe trait Alloc {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -736,7 +736,7 @@ pub unsafe trait Alloc {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `realloc` is.
     ///
@@ -770,7 +770,7 @@ pub unsafe trait Alloc {
     /// memory block referenced by `ptr` has not been transferred, and
     /// the contents of the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -827,7 +827,7 @@ pub unsafe trait Alloc {
     /// the memory block has not been transferred, and the contents of
     /// the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -920,7 +920,7 @@ pub unsafe trait Alloc {
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
@@ -993,7 +993,7 @@ pub unsafe trait Alloc {
     /// The returned block is suitable for passing to the
     /// `alloc`/`realloc` methods of this allocator.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -1037,7 +1037,7 @@ pub unsafe trait Alloc {
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index daf556795fa..d734ae6a2cf 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -16,16 +16,13 @@
 //!
 //! [arc]: struct.Arc.html
 
-use boxed::Box;
-
 use core::sync::atomic;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
 use core::borrow;
 use core::fmt;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
-use core::mem;
-use core::mem::uninitialized;
+use core::mem::{self, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
@@ -34,7 +31,10 @@ use core::hash::{Hash, Hasher};
 use core::{isize, usize};
 use core::convert::From;
 
-use heap::{Heap, Alloc, Layout};
+use heap::{Heap, Alloc, Layout, box_free};
+use boxed::Box;
+use string::String;
+use vec::Vec;
 
 /// A soft limit on the amount of references that may be made to an `Arc`.
 ///
@@ -278,7 +278,7 @@ impl<T> Arc<T> {
         let x: Box<_> = box ArcInner {
             strong: atomic::AtomicUsize::new(1),
             weak: atomic::AtomicUsize::new(1),
-            data: data,
+            data,
         };
         Arc { ptr: Shared::from(Box::into_unique(x)) }
     }
@@ -532,6 +532,141 @@ impl<T: ?Sized> Arc<T> {
     }
 }
 
+impl<T: ?Sized> Arc<T> {
+    // Allocates an `ArcInner<T>` with sufficient space for an unsized value
+    unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
+        // Create a fake ArcInner to find allocation size and alignment
+        let fake_ptr = ptr as *mut ArcInner<T>;
+
+        let layout = Layout::for_value(&*fake_ptr);
+
+        let mem = Heap.alloc(layout)
+            .unwrap_or_else(|e| Heap.oom(e));
+
+        // Initialize the real ArcInner
+        let inner = set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>;
+
+        ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
+        ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
+
+        inner
+    }
+
+    fn from_box(v: Box<T>) -> Arc<T> {
+        unsafe {
+            let bptr = Box::into_raw(v);
+
+            let value_size = size_of_val(&*bptr);
+            let ptr = Self::allocate_for_ptr(bptr);
+
+            // Copy value as bytes
+            ptr::copy_nonoverlapping(
+                bptr as *const T as *const u8,
+                &mut (*ptr).data as *mut _ as *mut u8,
+                value_size);
+
+            // Free the allocation without dropping its contents
+            box_free(bptr);
+
+            Arc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+    ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+    ptr
+}
+
+impl<T> Arc<[T]> {
+    // Copy elements from slice into newly allocated Arc<[T]>
+    //
+    // Unsafe because the caller must either take ownership or bind `T: Copy`
+    unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
+        let v_ptr = v as *const [T];
+        let ptr = Self::allocate_for_ptr(v_ptr);
+
+        ptr::copy_nonoverlapping(
+            v.as_ptr(),
+            &mut (*ptr).data as *mut [T] as *mut T,
+            v.len());
+
+        Arc { ptr: Shared::new_unchecked(ptr) }
+    }
+}
+
+// Specialization trait used for From<&[T]>
+trait ArcFromSlice<T> {
+    fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
+    #[inline]
+    default fn from_slice(v: &[T]) -> Self {
+        // Panic guard while cloning T elements.
+        // In the event of a panic, elements that have been written
+        // into the new ArcInner will be dropped, then the memory freed.
+        struct Guard<T> {
+            mem: *mut u8,
+            elems: *mut T,
+            layout: Layout,
+            n_elems: usize,
+        }
+
+        impl<T> Drop for Guard<T> {
+            fn drop(&mut self) {
+                use core::slice::from_raw_parts_mut;
+
+                unsafe {
+                    let slice = from_raw_parts_mut(self.elems, self.n_elems);
+                    ptr::drop_in_place(slice);
+
+                    Heap.dealloc(self.mem, self.layout.clone());
+                }
+            }
+        }
+
+        unsafe {
+            let v_ptr = v as *const [T];
+            let ptr = Self::allocate_for_ptr(v_ptr);
+
+            let mem = ptr as *mut _ as *mut u8;
+            let layout = Layout::for_value(&*ptr);
+
+            // Pointer to first element
+            let elems = &mut (*ptr).data as *mut [T] as *mut T;
+
+            let mut guard = Guard{
+                mem: mem,
+                elems: elems,
+                layout: layout,
+                n_elems: 0,
+            };
+
+            for (i, item) in v.iter().enumerate() {
+                ptr::write(elems.offset(i as isize), item.clone());
+                guard.n_elems += 1;
+            }
+
+            // All clear. Forget the guard so it doesn't free the new ArcInner.
+            mem::forget(guard);
+
+            Arc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
+    #[inline]
+    fn from_slice(v: &[T]) -> Self {
+        unsafe { Arc::copy_from_slice(v) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Clone for Arc<T> {
     /// Makes a clone of the `Arc` pointer.
@@ -1216,8 +1351,56 @@ impl<T> From<T> for Arc<T> {
     }
 }
 
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Arc<[T]> {
+    #[inline]
+    fn from(v: &[T]) -> Arc<[T]> {
+        <Self as ArcFromSlice<T>>::from_slice(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Arc<str> {
+    #[inline]
+    fn from(v: &str) -> Arc<str> {
+        unsafe { mem::transmute(<Arc<[u8]>>::from(v.as_bytes())) }
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Arc<str> {
+    #[inline]
+    fn from(v: String) -> Arc<str> {
+        Arc::from(&v[..])
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Arc<T> {
+    #[inline]
+    fn from(v: Box<T>) -> Arc<T> {
+        Arc::from_box(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Arc<[T]> {
+    #[inline]
+    fn from(mut v: Vec<T>) -> Arc<[T]> {
+        unsafe {
+            let arc = Arc::copy_from_slice(&v);
+
+            // Allow the Vec to free its memory, but not destroy its contents
+            v.set_len(0);
+
+            arc
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
+    use std::boxed::Box;
     use std::clone::Clone;
     use std::sync::mpsc::channel;
     use std::mem::drop;
@@ -1520,6 +1703,113 @@ mod tests {
         }
         t.join().unwrap();
     }
+
+    #[test]
+    fn test_from_str() {
+        let r: Arc<str> = Arc::from("foo");
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_copy_from_slice() {
+        let s: &[u32] = &[1, 2, 3];
+        let r: Arc<[u32]> = Arc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_clone_from_slice() {
+        #[derive(Clone, Debug, Eq, PartialEq)]
+        struct X(u32);
+
+        let s: &[X] = &[X(1), X(2), X(3)];
+        let r: Arc<[X]> = Arc::from(s);
+
+        assert_eq!(&r[..], s);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clone_from_slice_panic() {
+        use std::string::{String, ToString};
+
+        struct Fail(u32, String);
+
+        impl Clone for Fail {
+            fn clone(&self) -> Fail {
+                if self.0 == 2 {
+                    panic!();
+                }
+                Fail(self.0, self.1.clone())
+            }
+        }
+
+        let s: &[Fail] = &[
+            Fail(0, "foo".to_string()),
+            Fail(1, "bar".to_string()),
+            Fail(2, "baz".to_string()),
+        ];
+
+        // Should panic, but not cause memory corruption
+        let _r: Arc<[Fail]> = Arc::from(s);
+    }
+
+    #[test]
+    fn test_from_box() {
+        let b: Box<u32> = box 123;
+        let r: Arc<u32> = Arc::from(b);
+
+        assert_eq!(*r, 123);
+    }
+
+    #[test]
+    fn test_from_box_str() {
+        use std::string::String;
+
+        let s = String::from("foo").into_boxed_str();
+        let r: Arc<str> = Arc::from(s);
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_from_box_slice() {
+        let s = vec![1, 2, 3].into_boxed_slice();
+        let r: Arc<[u32]> = Arc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_from_box_trait() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let b: Box<Display> = box 123;
+        let r: Arc<Display> = Arc::from(b);
+
+        assert_eq!(r.to_string(), "123");
+    }
+
+    #[test]
+    fn test_from_box_trait_zero_sized() {
+        use std::fmt::Debug;
+
+        let b: Box<Debug> = box ();
+        let r: Arc<Debug> = Arc::from(b);
+
+        assert_eq!(format!("{:?}", r), "()");
+    }
+
+    #[test]
+    fn test_from_vec() {
+        let v = vec![1, 2, 3];
+        let r: Arc<[u32]> = Arc::from(v);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs
index 988f8851625..57640af816a 100644
--- a/src/liballoc/binary_heap.rs
+++ b/src/liballoc/binary_heap.rs
@@ -853,9 +853,9 @@ impl<'a, T> Hole<'a, T> {
         debug_assert!(pos < data.len());
         let elt = ptr::read(&data[pos]);
         Hole {
-            data: data,
+            data,
             elt: Some(elt),
-            pos: pos,
+            pos,
         }
     }
 
@@ -1203,7 +1203,7 @@ where T: Clone + Ord {
         let place = Placer::make_place(self.data.place_back());
         BinaryHeapPlace {
             heap: ptr,
-            place: place,
+            place,
         }
     }
 }
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 6318d22059f..82aac4dbf63 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -169,7 +169,7 @@ fn make_place<T>() -> IntermediateBox<T> {
 
     IntermediateBox {
         ptr: p,
-        layout: layout,
+        layout,
         marker: marker::PhantomData,
     }
 }
@@ -633,7 +633,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
 /// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
 /// closures become directly usable.)
 ///
-/// ### Example
+/// # Examples
 ///
 /// Here is a snippet of code which creates a hashmap full of boxed
 /// once closures and then removes them one by one, calling each
diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs
index a51c70159db..f733c3332e2 100644
--- a/src/liballoc/btree/map.rs
+++ b/src/liballoc/btree/map.rs
@@ -234,7 +234,7 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
         match search::search_tree(self.root.as_mut(), key) {
             Found(handle) => {
                 Some(OccupiedEntry {
-                         handle: handle,
+                         handle,
                          length: &mut self.length,
                          _marker: PhantomData,
                      }
@@ -250,8 +250,8 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>
             Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
             GoDown(handle) => {
                 VacantEntry {
-                    key: key,
-                    handle: handle,
+                    key,
+                    handle,
                     length: &mut self.length,
                     _marker: PhantomData,
                 }
@@ -695,7 +695,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
         match search::search_tree(self.root.as_mut(), key) {
             Found(handle) => {
                 Some(OccupiedEntry {
-                         handle: handle,
+                         handle,
                          length: &mut self.length,
                          _marker: PhantomData,
                      }
@@ -866,15 +866,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
         match search::search_tree(self.root.as_mut(), &key) {
             Found(handle) => {
                 Occupied(OccupiedEntry {
-                    handle: handle,
+                    handle,
                     length: &mut self.length,
                     _marker: PhantomData,
                 })
             }
             GoDown(handle) => {
                 Vacant(VacantEntry {
-                    key: key,
-                    handle: handle,
+                    key,
+                    handle,
                     length: &mut self.length,
                     _marker: PhantomData,
                 })
diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs
index 0e61905131f..c1618043ce6 100644
--- a/src/liballoc/btree/node.rs
+++ b/src/liballoc/btree/node.rs
@@ -763,7 +763,7 @@ impl<Node: Copy, Type> Clone for Handle<Node, Type> {
 }
 
 impl<Node, Type> Handle<Node, Type> {
-    /// Retrieves the node that contains the edge of key/value pair this handle pointes to.
+    /// Retrieves the node that contains the edge of key/value pair this handle points to.
     pub fn into_node(self) -> Node {
         self.node
     }
@@ -776,8 +776,8 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar
         debug_assert!(idx < node.len());
 
         Handle {
-            node: node,
-            idx: idx,
+            node,
+            idx,
             _marker: PhantomData
         }
     }
@@ -850,8 +850,8 @@ impl<BorrowType, K, V, NodeType>
         debug_assert!(idx <= node.len());
 
         Handle {
-            node: node,
-            idx: idx,
+            node,
+            idx,
             _marker: PhantomData
         }
     }
@@ -1149,7 +1149,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
 
             let mut new_root = Root {
                 node: BoxedNode::from_internal(new_node),
-                height: height
+                height,
             };
 
             for i in 0..(new_len+1) {
@@ -1449,12 +1449,12 @@ impl<BorrowType, K, V, HandleType>
     > {
         match self.node.force() {
             ForceResult::Leaf(node) => ForceResult::Leaf(Handle {
-                node: node,
+                node,
                 idx: self.idx,
                 _marker: PhantomData
             }),
             ForceResult::Internal(node) => ForceResult::Internal(Handle {
-                node: node,
+                node,
                 idx: self.idx,
                 _marker: PhantomData
             })
diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 480fb4b9eaa..578d90c5ba9 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -211,7 +211,7 @@
 //!
 //! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully
 //!   represented as a UTF-8 string at all times. It is **not** expected that
-//!   all types implement the `Display` trait.
+//!   all types implement the [`Display`] trait.
 //! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types.
 //!   Output will typically represent the internal state as faithfully as possible.
 //!   The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 227fcfabcf1..2d41ed64810 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -60,8 +60,6 @@
 //! The [`heap`](heap/index.html) module defines the low-level interface to the
 //! default global allocator. It is not compatible with the libc allocator API.
 
-#![crate_name = "alloc"]
-#![crate_type = "rlib"]
 #![allow(unused_attributes)]
 #![unstable(feature = "alloc",
             reason = "this library is unlikely to be stabilized in its current \
@@ -121,7 +119,7 @@
 #![feature(unsize)]
 #![feature(allocator_internals)]
 
-#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))]
+#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice))]
 #![cfg_attr(test, feature(test, box_heap))]
 
 // Allow testing this library
diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs
index 850dd6adcf0..f9512cbe977 100644
--- a/src/liballoc/linked_list.rs
+++ b/src/liballoc/linked_list.rs
@@ -140,7 +140,7 @@ impl<T> Node<T> {
         Node {
             next: None,
             prev: None,
-            element: element,
+            element,
         }
     }
 
@@ -924,7 +924,7 @@ impl<'a, T> IterMut<'a, T> {
                 let node = Some(Shared::from(Box::into_unique(box Node {
                     next: Some(head),
                     prev: Some(prev),
-                    element: element,
+                    element,
                 })));
 
                 prev.as_mut().next = node;
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 6090fc3942a..841f9dc6414 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -60,8 +60,8 @@ impl<T, A: Alloc> RawVec<T, A> {
         // Unique::empty() doubles as "unallocated" and "zero-sized allocation"
         RawVec {
             ptr: Unique::empty(),
-            cap: cap,
-            a: a,
+            cap,
+            a,
         }
     }
 
@@ -104,8 +104,8 @@ impl<T, A: Alloc> RawVec<T, A> {
 
             RawVec {
                 ptr: Unique::new_unchecked(ptr as *mut _),
-                cap: cap,
-                a: a,
+                cap,
+                a,
             }
         }
     }
@@ -159,8 +159,8 @@ impl<T, A: Alloc> RawVec<T, A> {
     pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self {
         RawVec {
             ptr: Unique::new_unchecked(ptr),
-            cap: cap,
-            a: a,
+            cap,
+            a,
         }
     }
 }
@@ -176,7 +176,7 @@ impl<T> RawVec<T, Heap> {
     pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
         RawVec {
             ptr: Unique::new_unchecked(ptr),
-            cap: cap,
+            cap,
             a: Heap,
         }
     }
@@ -544,12 +544,12 @@ impl<T, A: Alloc> RawVec<T, A> {
     /// Attempts to ensure that the buffer contains at least enough space to hold
     /// `used_cap + needed_extra_cap` elements. If it doesn't already have
     /// enough capacity, will reallocate in place enough space plus comfortable slack
-    /// space to get amortized `O(1)` behaviour. Will limit this behaviour
+    /// space to get amortized `O(1)` behavior. Will limit this behaviour
     /// if it would needlessly cause itself to panic.
     ///
     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
     /// the requested space. This is not really unsafe, but the unsafe
-    /// code *you* write that relies on the behaviour of this function may break.
+    /// code *you* write that relies on the behavior of this function may break.
     ///
     /// Returns true if the reallocation attempt has succeeded, or false otherwise.
     ///
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index a2184054b37..47f537caf31 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -252,14 +252,15 @@ use core::hash::{Hash, Hasher};
 use core::intrinsics::abort;
 use core::marker;
 use core::marker::Unsize;
-use core::mem::{self, forget, size_of, size_of_val, uninitialized};
+use core::mem::{self, forget, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
 use core::convert::From;
 
 use heap::{Heap, Alloc, Layout, box_free};
-use raw_vec::RawVec;
+use string::String;
+use vec::Vec;
 
 struct RcBox<T: ?Sized> {
     strong: Cell<usize>,
@@ -311,7 +312,7 @@ impl<T> Rc<T> {
             ptr: Shared::from(Box::into_unique(box RcBox {
                 strong: Cell::new(1),
                 weak: Cell::new(1),
-                value: value,
+                value,
             })),
         }
     }
@@ -421,64 +422,6 @@ impl<T> Rc<T> {
     }
 }
 
-impl Rc<str> {
-    /// Constructs a new `Rc<str>` from a string slice.
-    #[doc(hidden)]
-    #[unstable(feature = "rustc_private",
-               reason = "for internal use in rustc",
-               issue = "27812")]
-    pub fn __from_str(value: &str) -> Rc<str> {
-        unsafe {
-            // Allocate enough space for `RcBox<str>`.
-            let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>();
-            let vec = RawVec::<usize>::with_capacity(aligned_len);
-            let ptr = vec.ptr();
-            forget(vec);
-            // Initialize fields of `RcBox<str>`.
-            *ptr.offset(0) = 1; // strong: Cell::new(1)
-            *ptr.offset(1) = 1; // weak: Cell::new(1)
-            ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
-            // Combine the allocation address and the string length into a fat pointer to `RcBox`.
-            let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
-            assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
-            Rc { ptr: Shared::new_unchecked(rcbox_ptr) }
-        }
-    }
-}
-
-impl<T> Rc<[T]> {
-    /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
-    #[doc(hidden)]
-    #[unstable(feature = "rustc_private",
-               reason = "for internal use in rustc",
-               issue = "27812")]
-    pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
-        unsafe {
-            let ptr: *mut RcBox<[T]> =
-                mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
-            // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
-            // we should have a better way of getting the size/align
-            // of a DST from its unsized part.
-            let ptr = Heap.alloc(Layout::for_value(&*ptr))
-                .unwrap_or_else(|e| Heap.oom(e));
-            let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
-
-            // Initialize the new RcBox.
-            ptr::write(&mut (*ptr).strong, Cell::new(1));
-            ptr::write(&mut (*ptr).weak, Cell::new(1));
-            ptr::copy_nonoverlapping(
-                value.as_ptr(),
-                &mut (*ptr).value as *mut [T] as *mut T,
-                value.len());
-
-            // Free the original allocation without freeing its (moved) contents.
-            box_free(Box::into_raw(value));
-
-            Rc { ptr: Shared::new_unchecked(ptr as *mut _) }
-        }
-    }
-}
-
 impl<T: ?Sized> Rc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
@@ -665,6 +608,140 @@ impl<T: Clone> Rc<T> {
     }
 }
 
+impl<T: ?Sized> Rc<T> {
+    // Allocates an `RcBox<T>` with sufficient space for an unsized value
+    unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
+        // Create a fake RcBox to find allocation size and alignment
+        let fake_ptr = ptr as *mut RcBox<T>;
+
+        let layout = Layout::for_value(&*fake_ptr);
+
+        let mem = Heap.alloc(layout)
+            .unwrap_or_else(|e| Heap.oom(e));
+
+        // Initialize the real RcBox
+        let inner = set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>;
+
+        ptr::write(&mut (*inner).strong, Cell::new(1));
+        ptr::write(&mut (*inner).weak, Cell::new(1));
+
+        inner
+    }
+
+    fn from_box(v: Box<T>) -> Rc<T> {
+        unsafe {
+            let bptr = Box::into_raw(v);
+
+            let value_size = size_of_val(&*bptr);
+            let ptr = Self::allocate_for_ptr(bptr);
+
+            // Copy value as bytes
+            ptr::copy_nonoverlapping(
+                bptr as *const T as *const u8,
+                &mut (*ptr).value as *mut _ as *mut u8,
+                value_size);
+
+            // Free the allocation without dropping its contents
+            box_free(bptr);
+
+            Rc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+    ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+    ptr
+}
+
+impl<T> Rc<[T]> {
+    // Copy elements from slice into newly allocated Rc<[T]>
+    //
+    // Unsafe because the caller must either take ownership or bind `T: Copy`
+    unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
+        let v_ptr = v as *const [T];
+        let ptr = Self::allocate_for_ptr(v_ptr);
+
+        ptr::copy_nonoverlapping(
+            v.as_ptr(),
+            &mut (*ptr).value as *mut [T] as *mut T,
+            v.len());
+
+        Rc { ptr: Shared::new_unchecked(ptr) }
+    }
+}
+
+trait RcFromSlice<T> {
+    fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
+    #[inline]
+    default fn from_slice(v: &[T]) -> Self {
+        // Panic guard while cloning T elements.
+        // In the event of a panic, elements that have been written
+        // into the new RcBox will be dropped, then the memory freed.
+        struct Guard<T> {
+            mem: *mut u8,
+            elems: *mut T,
+            layout: Layout,
+            n_elems: usize,
+        }
+
+        impl<T> Drop for Guard<T> {
+            fn drop(&mut self) {
+                use core::slice::from_raw_parts_mut;
+
+                unsafe {
+                    let slice = from_raw_parts_mut(self.elems, self.n_elems);
+                    ptr::drop_in_place(slice);
+
+                    Heap.dealloc(self.mem, self.layout.clone());
+                }
+            }
+        }
+
+        unsafe {
+            let v_ptr = v as *const [T];
+            let ptr = Self::allocate_for_ptr(v_ptr);
+
+            let mem = ptr as *mut _ as *mut u8;
+            let layout = Layout::for_value(&*ptr);
+
+            // Pointer to first element
+            let elems = &mut (*ptr).value as *mut [T] as *mut T;
+
+            let mut guard = Guard{
+                mem: mem,
+                elems: elems,
+                layout: layout,
+                n_elems: 0,
+            };
+
+            for (i, item) in v.iter().enumerate() {
+                ptr::write(elems.offset(i as isize), item.clone());
+                guard.n_elems += 1;
+            }
+
+            // All clear. Forget the guard so it doesn't free the new RcBox.
+            forget(guard);
+
+            Rc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+impl<T: Copy> RcFromSlice<T> for Rc<[T]> {
+    #[inline]
+    fn from_slice(v: &[T]) -> Self {
+        unsafe { Rc::copy_from_slice(v) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Rc<T> {
     type Target = T;
@@ -959,6 +1036,53 @@ impl<T> From<T> for Rc<T> {
     }
 }
 
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> {
+    #[inline]
+    fn from(v: &[T]) -> Rc<[T]> {
+        <Self as RcFromSlice<T>>::from_slice(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Rc<str> {
+    #[inline]
+    fn from(v: &str) -> Rc<str> {
+        unsafe { mem::transmute(<Rc<[u8]>>::from(v.as_bytes())) }
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Rc<str> {
+    #[inline]
+    fn from(v: String) -> Rc<str> {
+        Rc::from(&v[..])
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Rc<T> {
+    #[inline]
+    fn from(v: Box<T>) -> Rc<T> {
+        Rc::from_box(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Rc<[T]> {
+    #[inline]
+    fn from(mut v: Vec<T>) -> Rc<[T]> {
+        unsafe {
+            let rc = Rc::copy_from_slice(&v);
+
+            // Allow the Vec to free its memory, but not destroy its contents
+            v.set_len(0);
+
+            rc
+        }
+    }
+}
+
 /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
 /// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
 /// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
@@ -1465,6 +1589,113 @@ mod tests {
         assert!(Rc::ptr_eq(&five, &same_five));
         assert!(!Rc::ptr_eq(&five, &other_five));
     }
+
+    #[test]
+    fn test_from_str() {
+        let r: Rc<str> = Rc::from("foo");
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_copy_from_slice() {
+        let s: &[u32] = &[1, 2, 3];
+        let r: Rc<[u32]> = Rc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_clone_from_slice() {
+        #[derive(Clone, Debug, Eq, PartialEq)]
+        struct X(u32);
+
+        let s: &[X] = &[X(1), X(2), X(3)];
+        let r: Rc<[X]> = Rc::from(s);
+
+        assert_eq!(&r[..], s);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clone_from_slice_panic() {
+        use std::string::{String, ToString};
+
+        struct Fail(u32, String);
+
+        impl Clone for Fail {
+            fn clone(&self) -> Fail {
+                if self.0 == 2 {
+                    panic!();
+                }
+                Fail(self.0, self.1.clone())
+            }
+        }
+
+        let s: &[Fail] = &[
+            Fail(0, "foo".to_string()),
+            Fail(1, "bar".to_string()),
+            Fail(2, "baz".to_string()),
+        ];
+
+        // Should panic, but not cause memory corruption
+        let _r: Rc<[Fail]> = Rc::from(s);
+    }
+
+    #[test]
+    fn test_from_box() {
+        let b: Box<u32> = box 123;
+        let r: Rc<u32> = Rc::from(b);
+
+        assert_eq!(*r, 123);
+    }
+
+    #[test]
+    fn test_from_box_str() {
+        use std::string::String;
+
+        let s = String::from("foo").into_boxed_str();
+        let r: Rc<str> = Rc::from(s);
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_from_box_slice() {
+        let s = vec![1, 2, 3].into_boxed_slice();
+        let r: Rc<[u32]> = Rc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_from_box_trait() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let b: Box<Display> = box 123;
+        let r: Rc<Display> = Rc::from(b);
+
+        assert_eq!(r.to_string(), "123");
+    }
+
+    #[test]
+    fn test_from_box_trait_zero_sized() {
+        use std::fmt::Debug;
+
+        let b: Box<Debug> = box ();
+        let r: Rc<Debug> = Rc::from(b);
+
+        assert_eq!(format!("{:?}", r), "()");
+    }
+
+    #[test]
+    fn test_from_vec() {
+        let v = vec![1, 2, 3];
+        let r: Rc<[u32]> = Rc::from(v);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index ec7a2b6d0e8..7787ace9441 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -171,7 +171,7 @@ mod hack {
 impl<T> [T] {
     /// Returns the number of elements in the slice.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -185,7 +185,7 @@ impl<T> [T] {
 
     /// Returns `true` if the slice has a length of 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -523,7 +523,7 @@ impl<T> [T] {
 
     /// Reverses the order of elements in the slice, in place.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut v = [1, 2, 3];
@@ -580,7 +580,7 @@ impl<T> [T] {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['r', 'u', 's', 't'];
@@ -613,7 +613,7 @@ impl<T> [T] {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
@@ -1040,7 +1040,7 @@ impl<T> [T] {
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1074,7 +1074,7 @@ impl<T> [T] {
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1419,7 +1419,7 @@ impl<T> [T] {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
@@ -1445,7 +1445,7 @@ impl<T> [T] {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
@@ -1461,6 +1461,31 @@ impl<T> [T] {
         core_slice::SliceExt::copy_from_slice(self, src)
     }
 
+    /// Swaps all elements in `self` with those in `src`.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(swap_with_slice)]
+    ///
+    /// let mut src = [1, 2, 3];
+    /// let mut dst = [7, 8, 9];
+    ///
+    /// src.swap_with_slice(&mut dst);
+    /// assert_eq!(src, [7, 8, 9]);
+    /// assert_eq!(dst, [1, 2, 3]);
+    /// ```
+    #[unstable(feature = "swap_with_slice", issue = "44030")]
+    pub fn swap_with_slice(&mut self, src: &mut [T]) {
+        core_slice::SliceExt::swap_with_slice(self, src)
+    }
+
     /// Copies `self` into a new `Vec`.
     ///
     /// # Examples
@@ -1886,7 +1911,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
 
         // Push this run onto the stack.
         runs.push(Run {
-            start: start,
+            start,
             len: end - start,
         });
         end = start;
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 80317cd763b..79b2bbce2af 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -1714,7 +1714,7 @@ impl str {
     ///
     /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Basic usage
     ///
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 3ed5d2df1ab..b1919c7c968 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -38,7 +38,7 @@
 //! let message = s + " world!";
 //! ```
 //!
-//! If you have a vector of valid UTF-8 bytes, you can make a `String` out of
+//! If you have a vector of valid UTF-8 bytes, you can make a [`String`] out of
 //! it. You can do the reverse too.
 //!
 //! ```
@@ -82,7 +82,7 @@ use boxed::Box;
 ///
 /// # Examples
 ///
-/// You can create a `String` from a literal string with `String::from`:
+/// You can create a `String` from a literal string with [`String::from`]:
 ///
 /// ```
 /// let hello = String::from("Hello, world!");
@@ -98,6 +98,7 @@ use boxed::Box;
 /// hello.push_str("orld!");
 /// ```
 ///
+/// [`String::from`]: #method.from
 /// [`char`]: ../../std/primitive.char.html
 /// [`push`]: #method.push
 /// [`push_str`]: #method.push_str
@@ -155,17 +156,14 @@ use boxed::Box;
 /// takes_str(&s);
 /// ```
 ///
-/// [`&str`]: ../../std/primitive.str.html
-/// [`Deref`]: ../../std/ops/trait.Deref.html
-///
 /// This will create a [`&str`] from the `String` and pass it in. This
 /// conversion is very inexpensive, and so generally, functions will accept
 /// [`&str`]s as arguments unless they need a `String` for some specific
 /// reason.
 ///
 /// In certain cases Rust doesn't have enough information to make this
-/// conversion, known as `Deref` coercion. In the following example a string
-/// slice `&'a str` implements the trait `TraitExample`, and the function
+/// conversion, known as [`Deref`] coercion. In the following example a string
+/// slice [`&'a str`][`&str`] implements the trait `TraitExample`, and the function
 /// `example_func` takes anything that implements the trait. In this case Rust
 /// would need to make two implicit conversions, which Rust doesn't have the
 /// means to do. For that reason, the following example will not compile.
@@ -185,13 +183,13 @@ use boxed::Box;
 ///
 /// There are two options that would work instead. The first would be to
 /// change the line `example_func(&example_string);` to
-/// `example_func(example_string.as_str());`, using the method `as_str()`
+/// `example_func(example_string.as_str());`, using the method [`as_str()`]
 /// to explicitly extract the string slice containing the string. The second
 /// way changes `example_func(&example_string);` to
 /// `example_func(&*example_string);`. In this case we are dereferencing a
-/// `String` to a `str`, then referencing the `str` back to `&str`. The
-/// second way is more idiomatic, however both work to do the conversion
-/// explicitly rather than relying on the implicit conversion.
+/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to
+/// [`&str`]. The second way is more idiomatic, however both work to do the
+/// conversion explicitly rather than relying on the implicit conversion.
 ///
 /// # Representation
 ///
@@ -287,6 +285,10 @@ use boxed::Box;
 /// ```
 ///
 /// Here, there's no need to allocate more memory inside the loop.
+///
+/// [`&str`]: ../../std/primitive.str.html
+/// [`Deref`]: ../../std/ops/trait.Deref.html
+/// [`as_str()`]: struct.String.html#method.as_str
 #[derive(PartialOrd, Eq, Ord)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct String {
@@ -443,32 +445,22 @@ impl String {
     /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that
     /// the bytes are valid UTF-8, and then does the conversion.
     ///
-    /// [`&str`]: ../../std/primitive.str.html
-    /// [`u8`]: ../../std/primitive.u8.html
-    /// [`Vec<u8>`]: ../../std/vec/struct.Vec.html
-    ///
     /// If you are sure that the byte slice is valid UTF-8, and you don't want
     /// to incur the overhead of the validity check, there is an unsafe version
     /// of this function, [`from_utf8_unchecked`], which has the same behavior
     /// but skips the check.
     ///
-    /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked
-    ///
     /// This method will take care to not copy the vector, for efficiency's
     /// sake.
     ///
-    /// If you need a `&str` instead of a `String`, consider
+    /// If you need a [`&str`] instead of a `String`, consider
     /// [`str::from_utf8`].
     ///
-    /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html
-    ///
     /// The inverse of this method is [`as_bytes`].
     ///
-    /// [`as_bytes`]: #method.as_bytes
-    ///
     /// # Errors
     ///
-    /// Returns `Err` if the slice is not UTF-8 with a description as to why the
+    /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the
     /// provided bytes are not UTF-8. The vector you moved in is also included.
     ///
     /// # Examples
@@ -497,7 +489,14 @@ impl String {
     /// See the docs for [`FromUtf8Error`] for more details on what you can do
     /// with this error.
     ///
+    /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked
+    /// [`&str`]: ../../std/primitive.str.html
+    /// [`u8`]: ../../std/primitive.u8.html
+    /// [`Vec<u8>`]: ../../std/vec/struct.Vec.html
+    /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html
+    /// [`as_bytes`]: struct.String.html#method.as_bytes
     /// [`FromUtf8Error`]: struct.FromUtf8Error.html
+    /// [`Err`]: ../../stdresult/enum.Result.html#variant.Err
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
@@ -594,9 +593,11 @@ impl String {
         Cow::Owned(res)
     }
 
-    /// Decode a UTF-16 encoded vector `v` into a `String`, returning `Err`
+    /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`]
     /// if `v` contains any invalid data.
     ///
+    /// [`Err`]: ../../std/result/enum.Result.htlm#variant.Err
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -618,7 +619,7 @@ impl String {
         decode_utf16(v.iter().cloned()).collect::<Result<_, _>>().map_err(|_| FromUtf16Error(()))
     }
 
-    /// Decode a UTF-16 encoded vector `v` into a string, replacing
+    /// Decode a UTF-16 encoded slice `v` into a `String`, replacing
     /// invalid data with the replacement character (U+FFFD).
     ///
     /// # Examples
@@ -800,11 +801,12 @@ impl String {
     /// If you do not want this "at least" behavior, see the [`reserve_exact`]
     /// method.
     ///
-    /// [`reserve_exact`]: #method.reserve_exact
-    ///
     /// # Panics
     ///
-    /// Panics if the new capacity overflows `usize`.
+    /// Panics if the new capacity overflows [`usize`].
+    ///
+    /// [`reserve_exact`]: struct.String.html#method.reserve_exact
+    /// [`usize`]: ../../std/primitive.usize.html
     ///
     /// # Examples
     ///
@@ -909,7 +911,9 @@ impl String {
         self.vec.shrink_to_fit()
     }
 
-    /// Appends the given `char` to the end of this `String`.
+    /// Appends the given [`char`] to the end of this `String`.
+    ///
+    /// [`char`]: ../../std/primitive.char.html
     ///
     /// # Examples
     ///
@@ -990,7 +994,9 @@ impl String {
 
     /// Removes the last character from the string buffer and returns it.
     ///
-    /// Returns `None` if this `String` is empty.
+    /// Returns [`None`] if this `String` is empty.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -1019,7 +1025,7 @@ impl String {
         Some(ch)
     }
 
-    /// Removes a `char` from this `String` at a byte position and returns it.
+    /// Removes a [`char`] from this `String` at a byte position and returns it.
     ///
     /// This is an `O(n)` operation, as it requires copying every element in the
     /// buffer.
@@ -1061,6 +1067,57 @@ impl String {
         ch
     }
 
+    /// Retains only the characters specified by the predicate.
+    ///
+    /// In other words, remove all characters `c` such that `f(c)` returns `false`.
+    /// This method operates in place and preserves the order of the retained
+    /// characters.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(string_retain)]
+    ///
+    /// let mut s = String::from("f_o_ob_ar");
+    ///
+    /// s.retain(|c| c != '_');
+    ///
+    /// assert_eq!(s, "foobar");
+    /// ```
+    #[inline]
+    #[unstable(feature = "string_retain", issue = "43874")]
+    pub fn retain<F>(&mut self, mut f: F)
+        where F: FnMut(char) -> bool
+    {
+        let len = self.len();
+        let mut del_bytes = 0;
+        let mut idx = 0;
+
+        while idx < len {
+            let ch = unsafe {
+                self.slice_unchecked(idx, len).chars().next().unwrap()
+            };
+            let ch_len = ch.len_utf8();
+
+            if !f(ch) {
+                del_bytes += ch_len;
+            } else if del_bytes > 0 {
+                unsafe {
+                    ptr::copy(self.vec.as_ptr().offset(idx as isize),
+                              self.vec.as_mut_ptr().offset((idx - del_bytes) as isize),
+                              ch_len);
+                }
+            }
+
+            // Point idx to the next char
+            idx += ch_len;
+        }
+
+        if del_bytes > 0 {
+            unsafe { self.vec.set_len(len - del_bytes); }
+        }
+    }
+
     /// Inserts a character into this `String` at a byte position.
     ///
     /// This is an `O(n)` operation as it requires copying every element in the
@@ -1327,8 +1384,8 @@ impl String {
         let chars_iter = self[start..end].chars();
 
         Drain {
-            start: start,
-            end: end,
+            start,
+            end,
             iter: chars_iter,
             string: self_ptr,
         }
@@ -1338,7 +1395,7 @@ impl String {
     /// replaces with the given string, and yields the removed chars.
     /// The given string doesn’t need to be the same length as the range.
     ///
-    /// Note: The element range is removed when the `Splice` is dropped,
+    /// Note: The element range is removed when the [`Splice`] is dropped,
     /// even if the iterator is not consumed until the end.
     ///
     /// # Panics
@@ -1347,6 +1404,7 @@ impl String {
     /// boundary, or if they're out of bounds.
     ///
     /// [`char`]: ../../std/primitive.char.html
+    /// [`Splice`]: ../../std/string/struct.Splice.html
     ///
     /// # Examples
     ///
@@ -1391,18 +1449,21 @@ impl String {
         let chars_iter = self[start..end].chars();
 
         Splice {
-            start: start,
-            end: end,
+            start,
+            end,
             iter: chars_iter,
             string: self_ptr,
-            replace_with: replace_with
+            replace_with,
         }
     }
 
-    /// Converts this `String` into a `Box<str>`.
+    /// Converts this `String` into a [`Box`]`<`[`str`]`>`.
     ///
     /// This will drop any excess capacity.
     ///
+    /// [`Box`]: ../../std/boxed/struct.Box.html
+    /// [`str`]: ../../std/primitive.str.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index 27b23d14059..8f3e71ef794 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -10,12 +10,12 @@
 
 #![deny(warnings)]
 
-#![feature(alloc)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
 #![feature(inclusive_range_syntax)]
 #![feature(collection_placement)]
 #![feature(const_fn)]
+#![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
 #![feature(iterator_step_by)]
 #![feature(pattern)]
@@ -25,14 +25,11 @@
 #![feature(slice_rotate)]
 #![feature(splice)]
 #![feature(str_escape)]
-#![feature(test)]
+#![feature(string_retain)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 
-extern crate alloc;
-extern crate test;
 extern crate std_unicode;
-extern crate core;
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs
index b1731b2a5dc..f5c124c6b44 100644
--- a/src/liballoc/tests/string.rs
+++ b/src/liballoc/tests/string.rs
@@ -333,6 +333,26 @@ fn remove_bad() {
 }
 
 #[test]
+fn test_retain() {
+    let mut s = String::from("α_β_γ");
+
+    s.retain(|_| true);
+    assert_eq!(s, "α_β_γ");
+
+    s.retain(|c| c != '_');
+    assert_eq!(s, "αβγ");
+
+    s.retain(|c| c != 'β');
+    assert_eq!(s, "αγ");
+
+    s.retain(|c| c == 'α');
+    assert_eq!(s, "α");
+
+    s.retain(|_| false);
+    assert_eq!(s, "");
+}
+
+#[test]
 fn insert() {
     let mut s = "foobar".to_string();
     s.insert(0, 'ệ');
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 17f1229c206..670ea8089fc 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -801,3 +801,170 @@ fn overaligned_allocations() {
         assert!(v.as_ptr() as usize & 0xff == 0);
     }
 }
+
+#[test]
+fn drain_filter_empty() {
+    let mut vec: Vec<i32> = vec![];
+
+    {
+        let mut iter = vec.drain_filter(|_| true);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+    }
+    assert_eq!(vec.len(), 0);
+    assert_eq!(vec, vec![]);
+}
+
+#[test]
+fn drain_filter_zst() {
+    let mut vec = vec![(), (), (), (), ()];
+    let initial_len = vec.len();
+    let mut count = 0;
+    {
+        let mut iter = vec.drain_filter(|_| true);
+        assert_eq!(iter.size_hint(), (0, Some(initial_len)));
+        while let Some(_) = iter.next() {
+            count += 1;
+            assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+    }
+
+    assert_eq!(count, initial_len);
+    assert_eq!(vec.len(), 0);
+    assert_eq!(vec, vec![]);
+}
+
+#[test]
+fn drain_filter_false() {
+    let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+    let initial_len = vec.len();
+    let mut count = 0;
+    {
+        let mut iter = vec.drain_filter(|_| false);
+        assert_eq!(iter.size_hint(), (0, Some(initial_len)));
+        for _ in iter.by_ref() {
+            count += 1;
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+    }
+
+    assert_eq!(count, 0);
+    assert_eq!(vec.len(), initial_len);
+    assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+}
+
+#[test]
+fn drain_filter_true() {
+    let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+    let initial_len = vec.len();
+    let mut count = 0;
+    {
+        let mut iter = vec.drain_filter(|_| true);
+        assert_eq!(iter.size_hint(), (0, Some(initial_len)));
+        while let Some(_) = iter.next() {
+            count += 1;
+            assert_eq!(iter.size_hint(), (0, Some(initial_len - count)));
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+    }
+
+    assert_eq!(count, initial_len);
+    assert_eq!(vec.len(), 0);
+    assert_eq!(vec, vec![]);
+}
+
+#[test]
+fn drain_filter_complex() {
+
+    {   //                [+xxx++++++xxxxx++++x+x++]
+        let mut vec = vec![1,
+                           2, 4, 6,
+                           7, 9, 11, 13, 15, 17,
+                           18, 20, 22, 24, 26,
+                           27, 29, 31, 33,
+                           34,
+                           35,
+                           36,
+                           37, 39];
+
+        let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+        assert_eq!(removed.len(), 10);
+        assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
+
+        assert_eq!(vec.len(), 14);
+        assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
+    }
+
+    {   //                [xxx++++++xxxxx++++x+x++]
+        let mut vec = vec![2, 4, 6,
+                           7, 9, 11, 13, 15, 17,
+                           18, 20, 22, 24, 26,
+                           27, 29, 31, 33,
+                           34,
+                           35,
+                           36,
+                           37, 39];
+
+        let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+        assert_eq!(removed.len(), 10);
+        assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
+
+        assert_eq!(vec.len(), 13);
+        assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]);
+    }
+
+    {   //                [xxx++++++xxxxx++++x+x]
+        let mut vec = vec![2, 4, 6,
+                           7, 9, 11, 13, 15, 17,
+                           18, 20, 22, 24, 26,
+                           27, 29, 31, 33,
+                           34,
+                           35,
+                           36];
+
+        let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+        assert_eq!(removed.len(), 10);
+        assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]);
+
+        assert_eq!(vec.len(), 11);
+        assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]);
+    }
+
+    {   //                [xxxxxxxxxx+++++++++++]
+        let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+                           1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
+
+        let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+        assert_eq!(removed.len(), 10);
+        assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
+
+        assert_eq!(vec.len(), 10);
+        assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
+    }
+
+    {   //                [+++++++++++xxxxxxxxxx]
+        let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
+                           2, 4, 6, 8, 10, 12, 14, 16, 18, 20];
+
+        let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+        assert_eq!(removed.len(), 10);
+        assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]);
+
+        assert_eq!(vec.len(), 10);
+        assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
+    }
+}
+
+
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 5f68e59289d..8141851b8c9 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -1728,9 +1728,9 @@ impl<T> IntoIterator for Vec<T> {
             mem::forget(self);
             IntoIter {
                 buf: Shared::new_unchecked(begin),
-                cap: cap,
+                cap,
                 ptr: begin,
-                end: end,
+                end,
             }
         }
     }
@@ -1960,6 +1960,65 @@ impl<T> Vec<T> {
         }
     }
 
+    /// Creates an iterator which uses a closure to determine if an element should be removed.
+    ///
+    /// If the closure returns true, then the element is removed and yielded.
+    /// If the closure returns false, it will try again, and call the closure
+    /// on the next element, seeing if it passes the test.
+    ///
+    /// Using this method is equivalent to the following code:
+    ///
+    /// ```
+    /// # let some_predicate = |x: &mut i32| { *x == 2 };
+    /// # let mut vec = vec![1, 2, 3, 4, 5];
+    /// let mut i = 0;
+    /// while i != vec.len() {
+    ///     if some_predicate(&mut vec[i]) {
+    ///         let val = vec.remove(i);
+    ///         // your code here
+    ///     }
+    ///     i += 1;
+    /// }
+    /// ```
+    ///
+    /// But `drain_filter` is easier to use. `drain_filter` is also more efficient,
+    /// because it can backshift the elements of the array in bulk.
+    ///
+    /// Note that `drain_filter` also lets you mutate every element in the filter closure,
+    /// regardless of whether you choose to keep or remove it.
+    ///
+    ///
+    /// # Examples
+    ///
+    /// Splitting an array into evens and odds, reusing the original allocation:
+    ///
+    /// ```
+    /// #![feature(drain_filter)]
+    /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
+    ///
+    /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
+    /// let odds = numbers;
+    ///
+    /// assert_eq!(evens, vec![2, 4, 6, 8, 14]);
+    /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
+    /// ```
+    #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
+    pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<T, F>
+        where F: FnMut(&mut T) -> bool,
+    {
+        let old_len = self.len();
+
+        // Guard against us getting leaked (leak amplification)
+        unsafe { self.set_len(0); }
+
+        DrainFilter {
+            vec: self,
+            idx: 0,
+            del: 0,
+            old_len,
+            pred: filter,
+        }
+    }
 }
 
 /// Extend implementation that copies elements out of references before pushing them onto the Vec.
@@ -2602,3 +2661,57 @@ impl<'a, T> Drain<'a, T> {
         self.tail_start = new_tail_start;
     }
 }
+
+/// An iterator produced by calling `drain_filter` on Vec.
+#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
+#[derive(Debug)]
+pub struct DrainFilter<'a, T: 'a, F>
+    where F: FnMut(&mut T) -> bool,
+{
+    vec: &'a mut Vec<T>,
+    idx: usize,
+    del: usize,
+    old_len: usize,
+    pred: F,
+}
+
+#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
+impl<'a, T, F> Iterator for DrainFilter<'a, T, F>
+    where F: FnMut(&mut T) -> bool,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        unsafe {
+            while self.idx != self.old_len {
+                let i = self.idx;
+                self.idx += 1;
+                let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len);
+                if (self.pred)(&mut v[i]) {
+                    self.del += 1;
+                    return Some(ptr::read(&v[i]));
+                } else if self.del > 0 {
+                    v.swap(i - self.del, i);
+                }
+            }
+            None
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (0, Some(self.old_len - self.idx))
+    }
+}
+
+#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")]
+impl<'a, T, F> Drop for DrainFilter<'a, T, F>
+    where F: FnMut(&mut T) -> bool,
+{
+    fn drop(&mut self) {
+        for _ in self.by_ref() { }
+
+        unsafe {
+            self.vec.set_len(self.old_len - self.del);
+        }
+    }
+}
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index 2068c2c9c5f..00def2a1eac 100644
--- a/src/liballoc/vec_deque.rs
+++ b/src/liballoc/vec_deque.rs
@@ -459,10 +459,12 @@ impl<T> VecDeque<T> {
     ///
     /// `i` and `j` may be equal.
     ///
-    /// Fails if there is no element with either index.
-    ///
     /// Element at index 0 is the front of the queue.
     ///
+    /// # Panics
+    ///
+    /// Panics if either index is out of bounds.
+    ///
     /// # Examples
     ///
     /// ```
@@ -2442,7 +2444,7 @@ impl<T> From<Vec<T>> for VecDeque<T> {
             VecDeque {
                 tail: 0,
                 head: len,
-                buf: buf,
+                buf,
             }
         }
     }
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index 085f62f4b0f..41193f6a41f 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -93,29 +93,7 @@ fn main() {
        .env("AR", &ar)
        .env("RANLIB", format!("{} s", ar.display()));
 
-    if target.contains("windows") {
-        // A bit of history here, this used to be --enable-lazy-lock added in
-        // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
-        // was also reported to MinGW:
-        //
-        //  http://sourceforge.net/p/mingw-w64/bugs/395/
-        //
-        // When updating jemalloc to 4.0, however, it was found that binaries
-        // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
-        // that a thread was unlocking a mutex it never locked. Disabling this
-        // "lazy lock" option seems to fix the issue, but it was enabled by
-        // default for MinGW targets in 13473c7 for jemalloc.
-        //
-        // As a result of all that, force disabling lazy lock on Windows, and
-        // after reading some code it at least *appears* that the initialization
-        // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
-        // hopefully...
-        //
-        // tl;dr: make windows behave like other platforms by disabling lazy
-        //        locking, but requires passing an option due to a historical
-        //        default with jemalloc.
-        cmd.arg("--disable-lazy-lock");
-    } else if target.contains("ios") {
+    if target.contains("ios") {
         cmd.arg("--disable-tls");
     } else if target.contains("android") {
         // We force android to have prefixed symbols because apparently
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 3a9cc1dd5a6..efefabc974c 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "alloc_jemalloc"]
-#![crate_type = "rlib"]
 #![no_std]
 #![unstable(feature = "alloc_jemalloc",
             reason = "this library is unlikely to be stabilized in its current \
@@ -21,7 +19,7 @@
 #![feature(libc)]
 #![feature(linkage)]
 #![feature(staged_api)]
-#![cfg_attr(dummy_jemalloc, allow(dead_code))]
+#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
 
 extern crate alloc;
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 9a7cba21e3c..1defe308713 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "alloc_system"]
-#![crate_type = "rlib"]
 #![no_std]
 #![deny(warnings)]
 #![unstable(feature = "alloc_system",
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 8e3b3f2074d..96fcc81e8e6 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -18,9 +18,6 @@
 //! This crate implements `TypedArena`, a simple arena that can only hold
 //! objects of a single type.
 
-#![crate_name = "arena"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
diff --git a/src/libbacktrace/config.sub b/src/libbacktrace/config.sub
index da6d1b6826a..40ea5dfe115 100644
--- a/src/libbacktrace/config.sub
+++ b/src/libbacktrace/config.sub
@@ -1,8 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2016 Free Software Foundation, Inc.
+#   Copyright 1992-2017 Free Software Foundation, Inc.
 
-timestamp='2016-01-01'
+timestamp='2017-04-02'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2017 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -117,7 +117,7 @@ case $maybe_os in
   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
   knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
-  kopensolaris*-gnu* | \
+  kopensolaris*-gnu* | cloudabi*-eabi* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
@@ -263,7 +263,7 @@ case $basic_machine in
 	| fido | fr30 | frv | ft32 \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| hexagon \
-	| i370 | i860 | i960 | ia64 \
+	| i370 | i860 | i960 | ia16 | ia64 \
 	| ip2k | iq2000 \
 	| k1om \
 	| le32 | le64 \
@@ -301,6 +301,7 @@ case $basic_machine in
 	| open8 | or1k | or1knd | or32 \
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
 	| pyramid \
 	| riscv32 | riscv64 \
 	| rl78 | rx \
@@ -314,6 +315,7 @@ case $basic_machine in
 	| ubicom32 \
 	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
 	| visium \
+	| wasm32 \
 	| we32k \
 	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
@@ -387,7 +389,7 @@ case $basic_machine in
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| hexagon-* \
-	| i*86-* | i860-* | i960-* | ia64-* \
+	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
 	| ip2k-* | iq2000-* \
 	| k1om-* \
 	| le32-* | le64-* \
@@ -428,6 +430,7 @@ case $basic_machine in
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
 	| pyramid-* \
 	| riscv32-* | riscv64-* \
 	| rl78-* | romp-* | rs6000-* | rx-* \
@@ -444,6 +447,7 @@ case $basic_machine in
 	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
 	| vax-* \
 	| visium-* \
+	| wasm32-* \
 	| we32k-* \
 	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
@@ -643,6 +647,14 @@ case $basic_machine in
 		basic_machine=m68k-bull
 		os=-sysv3
 		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
 	ebmon29k)
 		basic_machine=a29k-amd
 		os=-ebmon
@@ -938,6 +950,9 @@ case $basic_machine in
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
+	nsx-tandem)
+		basic_machine=nsx-tandem
+		;;
 	op50n-* | op60c-*)
 		basic_machine=hppa1.1-oki
 		os=-proelf
@@ -1022,7 +1037,7 @@ case $basic_machine in
 	ppc-* | ppcbe-*)
 		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	ppcle | powerpclittle | ppc-le | powerpc-little)
+	ppcle | powerpclittle)
 		basic_machine=powerpcle-unknown
 		;;
 	ppcle-* | powerpclittle-*)
@@ -1032,7 +1047,7 @@ case $basic_machine in
 		;;
 	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
-	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+	ppc64le | powerpc64little)
 		basic_machine=powerpc64le-unknown
 		;;
 	ppc64le-* | powerpc64little-*)
@@ -1233,6 +1248,9 @@ case $basic_machine in
 		basic_machine=a29k-wrs
 		os=-vxworks
 		;;
+	wasm32)
+		basic_machine=wasm32-unknown
+		;;
 	w65*)
 		basic_machine=w65-wdc
 		os=-none
@@ -1382,14 +1400,14 @@ case $os in
 	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
 	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
 	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
-	      | -bitrig* | -openbsd* | -solidbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
 	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
 	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
 	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
 	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
 	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
@@ -1399,7 +1417,7 @@ case $os in
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
-	      | -onefs* | -tirtos*)
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1531,6 +1549,8 @@ case $os in
 		;;
 	-nacl*)
 		;;
+	-ios)
+		;;
 	-none)
 		;;
 	*)
@@ -1626,6 +1646,9 @@ case $basic_machine in
 	sparc-* | *-sun)
 		os=-sunos4.1.1
 		;;
+	pru-*)
+		os=-elf
+		;;
 	*-be)
 		os=-beos
 		;;
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 38143593eb1..55316db3d5a 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "collections"]
-#![crate_type = "rlib"]
 #![allow(unused_attributes)]
 #![unstable(feature = "collections",
             reason = "this library is unlikely to be stabilized in its current \
diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins
-Subproject 5e49856003f33aa5781a0edca148be21025e18e
+Subproject 6b9281d2b2f0ebb94838814b1e8ace2de4b7035
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 37bd57034a7..4b7706bac30 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -89,7 +89,7 @@ macro_rules! __impl_slice_eq2 {
     }
 }
 
-// macro for implementing n-ary tuple functions and operations
+// macro for implementing n-element array functions and operations
 macro_rules! array_impls {
     ($($N:expr)+) => {
         $(
@@ -124,6 +124,7 @@ macro_rules! array_impls {
             }
 
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[cfg(stage0)]
             impl<T:Copy> Clone for [T; $N] {
                 fn clone(&self) -> [T; $N] {
                     *self
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 6068f1a7961..e0a3b8d52f4 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -809,7 +809,7 @@ impl<T: ?Sized> RefCell<T> {
     /// [`borrow_mut`] method instead if `self` isn't mutable.
     ///
     /// Also, please be aware that this method is only for special circumstances and is usually
-    /// not you want. In case of doubt, use [`borrow_mut`] instead.
+    /// not what you want. In case of doubt, use [`borrow_mut`] instead.
     ///
     /// [`borrow_mut`]: #method.borrow_mut
     ///
@@ -998,7 +998,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// A method would interfere with methods of the same name on the contents
     /// of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, Ref};
@@ -1040,7 +1040,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// `RefMut::map(...)`.  A method would interfere with methods of the same
     /// name on the contents of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, RefMut};
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 8856d0b8cb9..2dc51718b97 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -88,6 +88,7 @@
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), lang = "clone")]
 pub trait Clone : Sized {
     /// Returns a copy of the value.
     ///
@@ -131,6 +132,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData
 pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
 impl<'a, T: ?Sized> Clone for &'a T {
     /// Returns a shallow copy of the reference.
     #[inline]
@@ -140,6 +142,7 @@ impl<'a, T: ?Sized> Clone for &'a T {
 macro_rules! clone_impl {
     ($t:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg(stage0)]
         impl Clone for $t {
             /// Returns a deep copy of the value.
             #[inline]
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 322df6e5b47..b594c886b64 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -18,7 +18,7 @@ struct PadAdapter<'a, 'b: 'a> {
 impl<'a, 'b: 'a> PadAdapter<'a, 'b> {
     fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> {
         PadAdapter {
-            fmt: fmt,
+            fmt,
             on_newline: false,
         }
     }
@@ -58,7 +58,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
 /// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -94,8 +94,8 @@ pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
                                 -> DebugStruct<'a, 'b> {
     let result = fmt.write_str(name);
     DebugStruct {
-        fmt: fmt,
-        result: result,
+        fmt,
+        result,
         has_fields: false,
     }
 }
@@ -153,7 +153,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
 /// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -185,8 +185,8 @@ pub struct DebugTuple<'a, 'b: 'a> {
 pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> {
     let result = fmt.write_str(name);
     DebugTuple {
-        fmt: fmt,
-        result: result,
+        fmt,
+        result,
         fields: 0,
         empty_name: name.is_empty(),
     }
@@ -290,7 +290,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
 /// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -317,8 +317,8 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b
     let result = write!(fmt, "{{");
     DebugSet {
         inner: DebugInner {
-            fmt: fmt,
-            result: result,
+            fmt,
+            result,
             has_fields: false,
         },
     }
@@ -361,7 +361,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
 /// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -388,8 +388,8 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a,
     let result = write!(fmt, "[");
     DebugList {
         inner: DebugInner {
-            fmt: fmt,
-            result: result,
+            fmt,
+            result,
             has_fields: false,
         },
     }
@@ -432,7 +432,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
 /// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -460,8 +460,8 @@ pub struct DebugMap<'a, 'b: 'a> {
 pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
     let result = write!(fmt, "{{");
     DebugMap {
-        fmt: fmt,
-        result: result,
+        fmt,
+        result,
         has_fields: false,
     }
 }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 97839844087..cf6262bda97 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -334,9 +334,9 @@ impl<'a> Arguments<'a> {
     pub fn new_v1(pieces: &'a [&'a str],
                   args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
         Arguments {
-            pieces: pieces,
+            pieces,
             fmt: None,
-            args: args
+            args,
         }
     }
 
@@ -353,9 +353,9 @@ impl<'a> Arguments<'a> {
                             args: &'a [ArgumentV1<'a>],
                             fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {
         Arguments {
-            pieces: pieces,
+            pieces,
             fmt: Some(fmt),
-            args: args
+            args,
         }
     }
 
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 2000ba91460..a8b84203d6a 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -240,7 +240,12 @@ pub trait Hash {
 /// [`write_u8`]: #method.write_u8
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hasher {
-    /// Completes a round of hashing, producing the output hash generated.
+    /// Returns the hash value for the values written so far.
+    ///
+    /// Despite its name, the method does not reset the hasher’s internal
+    /// state. Additional [`write`]s will continue from the current value.
+    /// If you need to start a fresh hash value, you will have to create
+    /// a new hasher.
     ///
     /// # Examples
     ///
@@ -253,6 +258,8 @@ pub trait Hasher {
     ///
     /// println!("Hash is {:x}!", hasher.finish());
     /// ```
+    ///
+    /// ['write']: #tymethod.write
     #[stable(feature = "rust1", since = "1.0.0")]
     fn finish(&self) -> u64;
 
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 2472efa14b3..7c009114afe 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -605,7 +605,7 @@ pub trait Iterator {
     /// closure returns [`None`], it will try again, and call the closure on the
     /// next element, seeing if it will return [`Some`].
     ///
-    /// Why `filter_map` and not just [`filter`].[`map`]? The key is in this
+    /// Why `filter_map` and not just [`filter`] and [`map`]? The key is in this
     /// part:
     ///
     /// [`filter`]: #method.filter
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index 22b997a768e..ebedfe1d743 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -840,8 +840,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
     type Item = (A::Item, B::Item);
     default fn new(a: A, b: B) -> Self {
         Zip {
-            a: a,
-            b: b,
+            a,
+            b,
             index: 0, // unused
             len: 0, // unused
         }
@@ -903,10 +903,10 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
     fn new(a: A, b: B) -> Self {
         let len = cmp::min(a.len(), b.len());
         Zip {
-            a: a,
-            b: b,
+            a,
+            b,
             index: 0,
-            len: len,
+            len,
         }
     }
 
diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs
index 19098f036ac..2af129a67bd 100644
--- a/src/libcore/iter/traits.rs
+++ b/src/libcore/iter/traits.rs
@@ -744,7 +744,7 @@ impl<I, T, E> ResultShunt<I, E>
 
     fn new(iter: I) -> Self {
         ResultShunt {
-            iter: iter,
+            iter,
             error: None,
         }
     }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 546d2a21939..c270c6ae0db 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -51,9 +51,7 @@
 // Since libcore defines many fundamental lang items, all tests live in a
 // separate crate, libcoretest, to avoid bizarre issues.
 
-#![crate_name = "core"]
 #![stable(feature = "core", since = "1.6.0")]
-#![crate_type = "rlib"]
 #![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/",
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 6f7adbe1e7a..4b866cab1ea 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -901,7 +901,7 @@ impl<T> ManuallyDrop<T> {
 
     /// Manually drops the contained value.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function runs the destructor of the contained value and thus the wrapped value
     /// now represents uninitialized data. It is up to the user of this method to ensure the
diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs
index 2a60292d023..12960fed045 100644
--- a/src/libcore/num/dec2flt/rawfp.rs
+++ b/src/libcore/num/dec2flt/rawfp.rs
@@ -102,10 +102,10 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp
     /// The number of bits in the exponent.
     const EXP_BITS: u8;
 
-    /// The number of bits in the singificand, *including* the hidden bit.
+    /// The number of bits in the significand, *including* the hidden bit.
     const SIG_BITS: u8;
 
-    /// The number of bits in the singificand, *excluding* the hidden bit.
+    /// The number of bits in the significand, *excluding* the hidden bit.
     const EXPLICIT_SIG_BITS: u8;
 
     /// The maximum legal exponent in fractional representation.
@@ -123,7 +123,7 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp
     /// `MIN_EXP` for integral representation, i.e., with the shift applied.
     const MIN_EXP_INT: i16;
 
-    /// The maximum normalized singificand in integral representation.
+    /// The maximum normalized significand in integral representation.
     const MAX_SIG: u64;
 
     /// The minimal normalized significand in integral representation.
diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs
index 6635d95155f..97bcba2f2ff 100644
--- a/src/libcore/num/diy_float.rs
+++ b/src/libcore/num/diy_float.rs
@@ -86,7 +86,7 @@ impl Fp {
         assert_eq!(self.f << edelta >> edelta, self.f);
         Fp {
             f: self.f << edelta,
-            e: e,
+            e,
         }
     }
 }
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index 74b9e7bf37d..beaa6e140a6 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -442,7 +442,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
         }
         FullDecoded::Finite(ref decoded) => {
             let (len, exp) = format_shortest(decoded, buf);
-            Formatted { sign: sign,
+            Formatted { sign,
                         parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
         }
     }
@@ -581,7 +581,7 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
 
             let trunc = if ndigits < maxlen { ndigits } else { maxlen };
             let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
-            Formatted { sign: sign,
+            Formatted { sign,
                         parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) }
         }
     }
@@ -652,7 +652,7 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
                     Formatted { sign: sign, parts: &parts[..1] }
                 }
             } else {
-                Formatted { sign: sign,
+                Formatted { sign,
                             parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
             }
         }
diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs
index 4971e825a6f..78326c3e639 100644
--- a/src/libcore/ops/try.rs
+++ b/src/libcore/ops/try.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/// A trait for customizing the behaviour of the `?` operator.
+/// A trait for customizing the behavior of the `?` operator.
 ///
 /// A type implementing `Try` is one that has a canonical way to view it
 /// in terms of a success/failure dichotomy.  This trait allows both
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index e35777d222c..63e9373e936 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -876,6 +876,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
 impl<T: ?Sized> Clone for *const T {
     #[inline]
     fn clone(&self) -> *const T {
@@ -884,6 +885,7 @@ impl<T: ?Sized> Clone for *const T {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(stage0)]
 impl<T: ?Sized> Clone for *mut T {
     #[inline]
     fn clone(&self) -> *mut T {
@@ -895,6 +897,7 @@ impl<T: ?Sized> Clone for *mut T {
 macro_rules! fnptr_impls_safety_abi {
     ($FnTy: ty, $($Arg: ident),*) => {
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg(stage0)]
         impl<Ret, $($Arg),*> Clone for $FnTy {
             #[inline]
             fn clone(&self) -> Self {
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 20cfb02afcc..ea064ca5c39 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -244,9 +244,12 @@ use fmt;
 use iter::{FromIterator, FusedIterator, TrustedLen};
 use ops;
 
-/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
+/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
 ///
 /// See the [`std::result`](index.html) module documentation for details.
+///
+/// [`Ok`]: enum.Result.html#variant.Ok
+/// [`Err`]: enum.Result.html#variant.Err
 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -269,7 +272,9 @@ impl<T, E> Result<T, E> {
     // Querying the contained values
     /////////////////////////////////////////////////////////////////////////
 
-    /// Returns `true` if the result is `Ok`.
+    /// Returns `true` if the result is [`Ok`].
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
     ///
     /// # Examples
     ///
@@ -291,7 +296,9 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Returns `true` if the result is `Err`.
+    /// Returns `true` if the result is [`Err`].
+    ///
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -433,10 +440,13 @@ impl<T, E> Result<T, E> {
     /////////////////////////////////////////////////////////////////////////
 
     /// Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a
-    /// contained `Ok` value, leaving an `Err` value untouched.
+    /// contained [`Ok`] value, leaving an [`Err`] value untouched.
     ///
     /// This function can be used to compose the results of two functions.
     ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    ///
     /// # Examples
     ///
     /// Print the numbers on each line of a string multiplied by two.
@@ -461,11 +471,14 @@ impl<T, E> Result<T, E> {
     }
 
     /// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a
-    /// contained `Err` value, leaving an `Ok` value untouched.
+    /// contained [`Err`] value, leaving an [`Ok`] value untouched.
     ///
     /// This function can be used to pass through a successful result while handling
     /// an error.
     ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -546,7 +559,10 @@ impl<T, E> Result<T, E> {
     // Boolean operations on the values, eager and lazy
     /////////////////////////////////////////////////////////////////////////
 
-    /// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`.
+    /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -578,7 +594,10 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Calls `op` if the result is `Ok`, otherwise returns the `Err` value of `self`.
+    /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// This function can be used for control flow based on `Result` values.
     ///
@@ -604,7 +623,10 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`.
+    /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -636,10 +658,13 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Calls `op` if the result is `Err`, otherwise returns the `Ok` value of `self`.
+    /// Calls `op` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`.
     ///
     /// This function can be used for control flow based on result values.
     ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -662,9 +687,12 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Unwraps a result, yielding the content of an `Ok`.
+    /// Unwraps a result, yielding the content of an [`Ok`].
     /// Else, it returns `optb`.
     ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -686,8 +714,11 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Unwraps a result, yielding the content of an `Ok`.
-    /// If the value is an `Err` then it calls `op` with its value.
+    /// Unwraps a result, yielding the content of an [`Ok`].
+    /// If the value is an [`Err`] then it calls `op` with its value.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -710,12 +741,15 @@ impl<T, E> Result<T, E> {
 }
 
 impl<T, E: fmt::Debug> Result<T, E> {
-    /// Unwraps a result, yielding the content of an `Ok`.
+    /// Unwraps a result, yielding the content of an [`Ok`].
     ///
     /// # Panics
     ///
-    /// Panics if the value is an `Err`, with a panic message provided by the
-    /// `Err`'s value.
+    /// Panics if the value is an [`Err`], with a panic message provided by the
+    /// [`Err`]'s value.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -739,12 +773,15 @@ impl<T, E: fmt::Debug> Result<T, E> {
         }
     }
 
-    /// Unwraps a result, yielding the content of an `Ok`.
+    /// Unwraps a result, yielding the content of an [`Ok`].
     ///
     /// # Panics
     ///
-    /// Panics if the value is an `Err`, with a panic message including the
-    /// passed message, and the content of the `Err`.
+    /// Panics if the value is an [`Err`], with a panic message including the
+    /// passed message, and the content of the [`Err`].
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -765,12 +802,16 @@ impl<T, E: fmt::Debug> Result<T, E> {
 }
 
 impl<T: fmt::Debug, E> Result<T, E> {
-    /// Unwraps a result, yielding the content of an `Err`.
+    /// Unwraps a result, yielding the content of an [`Err`].
     ///
     /// # Panics
     ///
-    /// Panics if the value is an `Ok`, with a custom panic message provided
-    /// by the `Ok`'s value.
+    /// Panics if the value is an [`Ok`], with a custom panic message provided
+    /// by the [`Ok`]'s value.
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
+    ///
     ///
     /// # Examples
     ///
@@ -792,12 +833,15 @@ impl<T: fmt::Debug, E> Result<T, E> {
         }
     }
 
-    /// Unwraps a result, yielding the content of an `Err`.
+    /// Unwraps a result, yielding the content of an [`Err`].
     ///
     /// # Panics
     ///
-    /// Panics if the value is an `Ok`, with a panic message including the
-    /// passed message, and the content of the `Ok`.
+    /// Panics if the value is an [`Ok`], with a panic message including the
+    /// passed message, and the content of the [`Ok`].
+    ///
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
@@ -820,8 +864,8 @@ impl<T: fmt::Debug, E> Result<T, E> {
 impl<T: Default, E> Result<T, E> {
     /// Returns the contained value or a default
     ///
-    /// Consumes the `self` argument then, if `Ok`, returns the contained
-    /// value, otherwise if `Err`, returns the default value for that
+    /// Consumes the `self` argument then, if [`Ok`], returns the contained
+    /// value, otherwise if [`Err`], returns the default value for that
     /// type.
     ///
     /// # Examples
@@ -829,7 +873,7 @@ impl<T: Default, E> Result<T, E> {
     /// Convert a string to an integer, turning poorly-formed strings
     /// into 0 (the default value for integers). [`parse`] converts
     /// a string to any other type that implements [`FromStr`], returning an
-    /// `Err` on error.
+    /// [`Err`] on error.
     ///
     /// ```
     /// let good_year_from_input = "1909";
@@ -843,6 +887,8 @@ impl<T: Default, E> Result<T, E> {
     ///
     /// [`parse`]: ../../std/primitive.str.html#method.parse
     /// [`FromStr`]: ../../std/str/trait.FromStr.html
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     #[inline]
     #[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
     pub fn unwrap_or_default(self) -> T {
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index fa0c482e55c..31d8266510a 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -212,6 +212,9 @@ pub trait SliceExt {
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
 
+    #[unstable(feature = "swap_with_slice", issue = "44030")]
+    fn swap_with_slice(&mut self, src: &mut [Self::Item]);
+
     #[stable(feature = "sort_unstable", since = "1.20.0")]
     fn sort_unstable(&mut self)
         where Self::Item: Ord;
@@ -300,7 +303,7 @@ impl<T> SliceExt for [T] {
     {
         Split {
             v: self,
-            pred: pred,
+            pred,
             finished: false
         }
     }
@@ -674,6 +677,16 @@ impl<T> SliceExt for [T] {
     }
 
     #[inline]
+    fn swap_with_slice(&mut self, src: &mut [T]) {
+        assert!(self.len() == src.len(),
+                "destination and source slices have different lengths");
+        unsafe {
+            ptr::swap_nonoverlapping(
+                self.as_mut_ptr(), src.as_mut_ptr(), self.len());
+        }
+    }
+
+    #[inline]
     fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> B,
               B: Borrow<Q>,
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 4c99fe97daf..a5f6e49a53b 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -2233,7 +2233,7 @@ impl StrExt for str {
     fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
         SplitN(SplitNInternal {
             iter: self.split(pat).0,
-            count: count,
+            count,
         })
     }
 
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index c4ff95b1d6a..edb7bed4520 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -290,7 +290,7 @@ impl<'a, C: CharEq> Pattern<'a> for CharEqPattern<C> {
     fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> {
         CharEqSearcher {
             ascii_only: self.0.only_ascii(),
-            haystack: haystack,
+            haystack,
             char_eq: self.0,
             char_indices: haystack.char_indices(),
         }
@@ -596,8 +596,8 @@ impl<'a, 'b> StrSearcher<'a, 'b> {
     fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> {
         if needle.is_empty() {
             StrSearcher {
-                haystack: haystack,
-                needle: needle,
+                haystack,
+                needle,
                 searcher: StrSearcherImpl::Empty(EmptyNeedle {
                     position: 0,
                     end: haystack.len(),
@@ -607,8 +607,8 @@ impl<'a, 'b> StrSearcher<'a, 'b> {
             }
         } else {
             StrSearcher {
-                haystack: haystack,
-                needle: needle,
+                haystack,
+                needle,
                 searcher: StrSearcherImpl::TwoWay(
                     TwoWaySearcher::new(needle.as_bytes(), haystack.len())
                 ),
@@ -899,13 +899,13 @@ impl TwoWaySearcher {
                 TwoWaySearcher::reverse_maximal_suffix(needle, period, true));
 
             TwoWaySearcher {
-                crit_pos: crit_pos,
-                crit_pos_back: crit_pos_back,
-                period: period,
+                crit_pos,
+                crit_pos_back,
+                period,
                 byteset: Self::byteset_create(&needle[..period]),
 
                 position: 0,
-                end: end,
+                end,
                 memory: 0,
                 memory_back: needle.len(),
             }
@@ -918,13 +918,13 @@ impl TwoWaySearcher {
             // reverse search.
 
             TwoWaySearcher {
-                crit_pos: crit_pos,
+                crit_pos,
                 crit_pos_back: crit_pos,
                 period: cmp::max(crit_pos, needle.len() - crit_pos) + 1,
                 byteset: Self::byteset_create(needle),
 
                 position: 0,
-                end: end,
+                end,
                 memory: usize::MAX, // Dummy value to signify that the period is long
                 memory_back: usize::MAX,
             }
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index d647a94a1ef..510e01db0e9 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -1632,7 +1632,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 ///     pub fn lock(&self) {
 ///         while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {}
-///         // This fence syncronizes-with store in `unlock`.
+///         // This fence synchronizes-with store in `unlock`.
 ///         fence(Ordering::Acquire);
 ///     }
 ///
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index a1249a5f22c..ed6923929d6 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -392,7 +392,7 @@ pub struct CycleIter<'a, T: 'a> {
 pub fn cycle<T>(data: &[T]) -> CycleIter<T> {
     CycleIter {
         index: 0,
-        data: data,
+        data,
     }
 }
 
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 84a3be99c27..ab2022b1824 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -26,7 +26,6 @@
 #![feature(inclusive_range)]
 #![feature(inclusive_range_syntax)]
 #![feature(iter_rfind)]
-#![feature(libc)]
 #![feature(nonzero)]
 #![feature(ord_max_min)]
 #![feature(rand)]
@@ -41,13 +40,10 @@
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_from)]
-#![feature(unicode)]
 #![feature(unique)]
 
 extern crate core;
 extern crate test;
-extern crate libc;
-extern crate std_unicode;
 extern crate rand;
 
 mod any;
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 51b0655f680..6bac55575fb 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -53,7 +53,7 @@ fn test_get_resource() {
 
     fn r(i: Rc<RefCell<isize>>) -> R {
         R {
-            i: i
+            i,
         }
     }
 
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
index 47e9c7c9038..555843dba41 100644
--- a/src/libcore/tuple.rs
+++ b/src/libcore/tuple.rs
@@ -22,6 +22,7 @@ macro_rules! tuple_impls {
     )+) => {
         $(
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[cfg(stage0)]
             impl<$($T:Clone),+> Clone for ($($T,)+) {
                 fn clone(&self) -> ($($T,)+) {
                     ($(self.$idx.clone(),)+)
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 493ce04f672..24430b2e377 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -14,9 +14,6 @@
 //! Parsing does not happen at runtime: structures of `std::fmt::rt` are
 //! generated instead.
 
-#![crate_name = "fmt_macros"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
@@ -284,7 +281,7 @@ impl<'a> Parser<'a> {
 
         Argument {
             position: pos,
-            format: format,
+            format,
         }
     }
 
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index f41fc5aa29f..a0eacc817ca 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -77,9 +77,6 @@
 //! }
 //! ```
 
-#![crate_name = "getopts"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
@@ -250,28 +247,28 @@ impl OptGroup {
             (0, _) => {
                 Opt {
                     name: Long((long_name)),
-                    hasarg: hasarg,
-                    occur: occur,
+                    hasarg,
+                    occur,
                     aliases: Vec::new(),
                 }
             }
             (1, 0) => {
                 Opt {
                     name: Short(short_name.chars().next().unwrap()),
-                    hasarg: hasarg,
-                    occur: occur,
+                    hasarg,
+                    occur,
                     aliases: Vec::new(),
                 }
             }
             (1, _) => {
                 Opt {
                     name: Long((long_name)),
-                    hasarg: hasarg,
-                    occur: occur,
+                    hasarg,
+                    occur,
                     aliases: vec![Opt {
                                       name: Short(short_name.chars().next().unwrap()),
-                                      hasarg: hasarg,
-                                      occur: occur,
+                                      hasarg,
+                                      occur,
                                       aliases: Vec::new(),
                                   }],
                 }
@@ -530,8 +527,8 @@ pub fn opt(short_name: &str,
         long_name: long_name.to_owned(),
         hint: hint.to_owned(),
         desc: desc.to_owned(),
-        hasarg: hasarg,
-        occur: occur,
+        hasarg,
+        occur,
     }
 }
 
@@ -681,9 +678,9 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
         }
     }
     Ok(Matches {
-        opts: opts,
-        vals: vals,
-        free: free,
+        opts,
+        vals,
+        free,
     })
 }
 
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index c01938f5e11..5b1cf2dee9a 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -11,7 +11,7 @@
 //! Generate files suitable for use with [Graphviz](http://www.graphviz.org/)
 //!
 //! The `render` function generates output (e.g. an `output.dot` file) for
-//! use with [Graphviz](http://www.graphviz.org/) by walking a labelled
+//! use with [Graphviz](http://www.graphviz.org/) by walking a labeled
 //! graph. (Graphviz can then automatically lay out the nodes and edges
 //! of the graph, and also optionally render the graph as an image or
 //! other [output formats](
@@ -150,7 +150,7 @@
 //!
 //! The output from this example renders four nodes that make up the
 //! Hasse-diagram for the subsets of the set `{x, y}`. Each edge is
-//! labelled with the &sube; character (specified using the HTML character
+//! labeled with the &sube; character (specified using the HTML character
 //! entity `&sube`).
 //!
 //! ```rust
@@ -283,9 +283,6 @@
 //!
 //! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
 
-#![crate_name = "graphviz"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
@@ -781,15 +778,15 @@ mod tests {
 
     fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge {
         Edge {
-            from: from,
-            to: to,
-            label: label,
-            style: style,
+            from,
+            to,
+            label,
+            style,
         }
     }
 
     struct LabelledGraph {
-        /// The name for this graph. Used for labelling generated `digraph`.
+        /// The name for this graph. Used for labeling generated `digraph`.
         name: &'static str,
 
         /// Each node is an index into `node_labels`; these labels are
@@ -848,9 +845,9 @@ mod tests {
                -> LabelledGraph {
             let count = node_labels.len();
             LabelledGraph {
-                name: name,
+                name,
                 node_labels: node_labels.to_opt_strs(),
-                edges: edges,
+                edges,
                 node_styles: match node_styles {
                     Some(nodes) => nodes,
                     None => vec![Style::None; count],
diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs
index 348180a48dc..8be6f647023 100644
--- a/src/libpanic_abort/lib.rs
+++ b/src/libpanic_abort/lib.rs
@@ -14,8 +14,6 @@
 //! simpler! That being said, it's not quite as versatile, but here goes!
 
 #![no_std]
-#![crate_name = "panic_abort"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_abort", issue = "32837")]
 #![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",
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index aadbeb96b2d..63e44f71a3a 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -74,7 +74,7 @@ pub unsafe fn panic(data: Box<Any + Send>) -> u32 {
     let exception = Box::new(Exception {
         _uwe: uw::_Unwind_Exception {
             exception_class: rust_exception_class(),
-            exception_cleanup: exception_cleanup,
+            exception_cleanup,
             private: [0; uw::unwinder_private_data_size],
         },
         cause: Some(data),
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs
index 90f4b364482..558286f4ec0 100644
--- a/src/libpanic_unwind/lib.rs
+++ b/src/libpanic_unwind/lib.rs
@@ -23,8 +23,6 @@
 //! module.
 
 #![no_std]
-#![crate_name = "panic_unwind"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![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",
@@ -36,7 +34,9 @@
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(libc)]
-#![feature(panic_unwind)]
+#![cfg_attr(not(any(target_env = "msvc",
+                    all(windows, target_arch = "x86_64", target_env = "gnu"))),
+            feature(panic_unwind))]
 #![feature(raw)]
 #![feature(staged_api)]
 #![feature(unwind_attributes)]
@@ -47,6 +47,7 @@
 
 extern crate alloc;
 extern crate libc;
+#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
 extern crate unwind;
 
 use core::intrinsics;
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 6a71e67676a..3f425c24a91 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -23,10 +23,7 @@
 //!
 //! See [the book](../book/first-edition/procedural-macros.html) for more.
 
-#![crate_name = "proc_macro"]
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![deny(warnings)]
 #![deny(missing_docs)]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -241,14 +238,14 @@ pub enum TokenNode {
 }
 
 /// Describes how a sequence of token trees is delimited.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
 pub enum Delimiter {
     /// `( ... )`
     Parenthesis,
-    /// `[ ... ]`
-    Brace,
     /// `{ ... }`
+    Brace,
+    /// `[ ... ]`
     Bracket,
     /// An implicit delimiter, e.g. `$var`, where $var is  `...`.
     None,
@@ -274,7 +271,7 @@ impl Term {
 }
 
 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
 pub enum Spacing {
     /// e.g. `+` is `Alone` in `+ =`.
diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs
index 1fb2c6b7dbb..6d0d6d115b7 100644
--- a/src/libprofiler_builtins/lib.rs
+++ b/src/libprofiler_builtins/lib.rs
@@ -14,7 +14,5 @@
 #![unstable(feature = "profiler_runtime_lib",
             reason = "internal implementation detail of rustc right now",
             issue = "0")]
-#![crate_name = "profiler_builtins"]
-#![crate_type = "rlib"]
 #![allow(unused_features)]
 #![feature(staged_api)]
diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs
index 9a42b82beff..e796197ab5b 100644
--- a/src/librand/distributions/gamma.rs
+++ b/src/librand/distributions/gamma.rs
@@ -127,9 +127,9 @@ impl GammaLargeShape {
     fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
         let d = shape - 1. / 3.;
         GammaLargeShape {
-            scale: scale,
+            scale,
             c: 1. / (9. * d).sqrt(),
-            d: d,
+            d,
         }
     }
 }
@@ -254,7 +254,7 @@ impl IndependentSample<f64> for ChiSquared {
 
 /// The Fisher F distribution `F(m, n)`.
 ///
-/// This distribution is equivalent to the ratio of two normalised
+/// This distribution is equivalent to the ratio of two normalized
 /// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
 /// (χ²(n)/n)`.
 pub struct FisherF {
diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs
index 67b9449981e..47967a719d3 100644
--- a/src/librand/distributions/mod.rs
+++ b/src/librand/distributions/mod.rs
@@ -149,7 +149,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
                 "WeightedChoice::new called with a total weight of 0");
 
         WeightedChoice {
-            items: items,
+            items,
             // we're likely to be generating numbers in this range
             // relatively often, so might as well cache it
             weight_range: Range::new(0, running_total),
diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs
index 33de11ab630..e1518dab21c 100644
--- a/src/librand/distributions/normal.rs
+++ b/src/librand/distributions/normal.rs
@@ -103,8 +103,8 @@ impl Normal {
     pub fn new(mean: f64, std_dev: f64) -> Normal {
         assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0");
         Normal {
-            mean: mean,
-            std_dev: std_dev,
+            mean,
+            std_dev,
         }
     }
 }
diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs
index be238b0b1ab..f2f8132e5b4 100644
--- a/src/librand/distributions/range.rs
+++ b/src/librand/distributions/range.rs
@@ -104,7 +104,7 @@ macro_rules! integer_impl {
                 let zone = unsigned_max - unsigned_max % range;
 
                 Range {
-                    low: low,
+                    low,
                     range: range as $ty,
                     accept_zone: zone as $ty
                 }
@@ -143,7 +143,7 @@ macro_rules! float_impl {
         impl SampleRange for $ty {
             fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                 Range {
-                    low: low,
+                    low,
                     range: high - low,
                     accept_zone: 0.0 // unused
                 }
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index 2baa07e370e..96ce0905e38 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -76,7 +76,7 @@ impl IsaacRng {
         rng
     }
 
-    /// Initialises `self`. If `use_rsl` is true, then use the current value
+    /// Initializes `self`. If `use_rsl` is true, then use the current value
     /// of `rsl` as a seed, otherwise construct one algorithmically (not
     /// randomly).
     fn init(&mut self, use_rsl: bool) {
@@ -367,7 +367,7 @@ impl Isaac64Rng {
         rng
     }
 
-    /// Initialises `self`. If `use_rsl` is true, then use the current value
+    /// Initializes `self`. If `use_rsl` is true, then use the current value
     /// of `rsl` as a seed, otherwise construct one algorithmically (not
     /// randomly).
     fn init(&mut self, use_rsl: bool) {
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 5e56b0d8ab1..90b3020fff9 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -16,8 +16,6 @@
 //! is not recommended to use this library directly, but rather the official
 //! interface through `std::rand`.
 
-#![crate_name = "rand"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
@@ -180,7 +178,7 @@ pub trait Rng: Sized {
     /// This method does *not* have a requirement to bear any fixed
     /// relationship to the other methods, for example, it does *not*
     /// have to result in the same output as progressively filling
-    /// `dest` with `self.gen::<u8>()`, and any such behaviour should
+    /// `dest` with `self.gen::<u8>()`, and any such behavior should
     /// not be relied upon.
     ///
     /// This method should guarantee that `dest` is entirely filled
@@ -418,10 +416,10 @@ impl Rand for XorShiftRng {
         }
         let (x, y, z, w) = tuple;
         XorShiftRng {
-            x: x,
-            y: y,
-            z: z,
-            w: w,
+            x,
+            y,
+            z,
+            w,
         }
     }
 }
diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs
index 21684e38f7b..2821b7a8232 100644
--- a/src/librand/reseeding.rs
+++ b/src/librand/reseeding.rs
@@ -24,7 +24,7 @@ pub struct ReseedingRng<R, Rsdr> {
     rng: R,
     generation_threshold: usize,
     bytes_generated: usize,
-    /// Controls the behaviour when reseeding the RNG.
+    /// Controls the behavior when reseeding the RNG.
     pub reseeder: Rsdr,
 }
 
@@ -38,10 +38,10 @@ impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
     /// * `reseeder`: the reseeding object to use.
     pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R, Rsdr> {
         ReseedingRng {
-            rng: rng,
-            generation_threshold: generation_threshold,
+            rng,
+            generation_threshold,
             bytes_generated: 0,
-            reseeder: reseeder,
+            reseeder,
         }
     }
 
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 5b609f192e1..01fff605283 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -411,6 +411,8 @@ define_dep_nodes!( <'tcx>
 
     [] BorrowCheckKrate,
     [] BorrowCheck(DefId),
+    [] MirBorrowCheck(DefId),
+
     [] RvalueCheck(DefId),
     [] Reachability,
     [] MirKeys,
@@ -520,6 +522,8 @@ define_dep_nodes!( <'tcx>
     [] DylibDepFormats(DefId),
     [] IsAllocator(DefId),
     [] IsPanicRuntime(DefId),
+    [] IsCompilerBuiltins(DefId),
+    [] HasGlobalAllocator(DefId),
     [] ExternCrate(DefId),
     [] LintLevels,
 );
diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs
index 9aa634770df..809d1dfcf60 100644
--- a/src/librustc/dep_graph/edges.rs
+++ b/src/librustc/dep_graph/edges.rs
@@ -244,8 +244,8 @@ impl DepGraphEdges {
         self.edges.insert((source, target));
     }
 
-    pub fn add_node(&mut self, node: DepNode) {
-        self.get_or_create_node(node);
+    pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex {
+        self.get_or_create_node(node)
     }
 
     #[inline]
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 4ca59132e0a..c487fc963ca 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashMap;
 use session::config::OutputType;
 use std::cell::{Ref, RefCell};
 use std::rc::Rc;
+use util::common::{ProfileQueriesMsg, profq_msg};
 
 use super::dep_node::{DepNode, DepKind, WorkProductId};
 use super::query::DepGraphQuery;
@@ -118,7 +119,13 @@ impl DepGraph {
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_task(key);
+            if cfg!(debug_assertions) {
+                profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
+            };
             let result = task(cx, arg);
+            if cfg!(debug_assertions) {
+                profq_msg(ProfileQueriesMsg::TaskEnd)
+            };
             let dep_node_index = data.edges.borrow_mut().pop_task(key);
             (result, dep_node_index)
         } else {
@@ -166,6 +173,14 @@ 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
+        }
+    }
+
     /// Indicates that a previous work product exists for `v`. This is
     /// invoked during initial start-up based on what nodes are clean
     /// (and what files exist in the incr. directory).
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 522c1531c59..412759e1142 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -362,6 +362,10 @@ Here are some simple examples of where you'll run into this error:
 struct Foo { x: &bool }        // error
 struct Foo<'a> { x: &'a bool } // correct
 
+struct Bar { x: Foo }
+               ^^^ expected lifetime parameter
+struct Bar<'a> { x: Foo<'a> } // correct
+
 enum Bar { A(u8), B(&bool), }        // error
 enum Bar<'a> { A(u8), B(&'a bool), } // correct
 
@@ -683,6 +687,21 @@ attributes:
 See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
 "##,
 
+E0214: r##"
+A generic type was described using parentheses rather than angle brackets. For
+example:
+
+```compile_fail,E0214
+fn main() {
+    let v: Vec(&str) = vec!["foo"];
+}
+```
+
+This is not currently supported: `v` should be defined as `Vec<&str>`.
+Parentheses are currently only used with generic types when defining parameters
+for `Fn`-family traits.
+"##,
+
 E0261: r##"
 When using a lifetime like `'a` in a type, it must be declared before being
 used.
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 2a0c76d99bf..d52cc26eaeb 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -617,17 +617,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
-    match *path_parameters {
-        AngleBracketedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.types);
-            walk_list!(visitor, visit_lifetime, &data.lifetimes);
-            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
-        }
-        ParenthesizedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.inputs);
-            walk_list!(visitor, visit_ty, &data.output);
-        }
-    }
+    walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
+    walk_list!(visitor, visit_ty, &path_parameters.types);
+    walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
 }
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
@@ -835,7 +827,16 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // NB: Deliberately force a compilation error if/when new fields are added.
-    let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
+    let ImplItem {
+        id: _,
+        hir_id: _,
+        name,
+        ref vis,
+        ref defaultness,
+        ref attrs,
+        ref node,
+        span
+    } = *impl_item;
 
     visitor.visit_name(span, name);
     visitor.visit_vis(vis);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 010c7f6171a..ac26cbc833d 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -45,21 +45,22 @@ use hir::map::{Definitions, DefKey, REGULAR_SPACE};
 use hir::map::definitions::DefPathData;
 use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
 use hir::def::{Def, PathResolution};
+use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_data_structures::indexed_vec::IndexVec;
 use session::Session;
+use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
 
 use std::collections::BTreeMap;
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
-
 use syntax::attr;
 use syntax::ast::*;
 use syntax::errors;
 use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::ptr::P;
-use syntax::codemap::{self, respan, Spanned};
+use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind};
 use syntax::std_inject;
 use syntax::symbol::{Symbol, keywords};
 use syntax::util::small_vector::SmallVector;
@@ -160,6 +161,12 @@ struct LoweredNodeId {
     hir_id: hir::HirId,
 }
 
+enum ParenthesizedGenericArgs {
+    Ok,
+    Warn,
+    Err,
+}
+
 impl<'a> LoweringContext<'a> {
     fn lower_crate(mut self, c: &Crate) -> hir::Crate {
         /// Full-crate AST visitor that inserts into a fresh
@@ -414,12 +421,14 @@ impl<'a> LoweringContext<'a> {
         Symbol::gensym(s)
     }
 
-    fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
+    fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, mut span: Span)
+        -> Span
+    {
         let mark = Mark::fresh(Mark::root());
         mark.set_expn_info(codemap::ExpnInfo {
             call_site: span,
             callee: codemap::NameAndSpan {
-                format: codemap::CompilerDesugaring(Symbol::intern(reason)),
+                format: codemap::CompilerDesugaring(reason),
                 span: Some(span),
                 allow_internal_unstable: true,
                 allow_internal_unsafe: false,
@@ -747,6 +756,21 @@ impl<'a> LoweringContext<'a> {
                     Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
                     _ => None
                 };
+                let parenthesized_generic_args = match resolution.base_def() {
+                    // `a::b::Trait(Args)`
+                    Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // `a::b::Trait(Args)::TraitItem`
+                    Def::Method(..) |
+                    Def::AssociatedConst(..) |
+                    Def::AssociatedTy(..) if i + 2 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // Avoid duplicated errors
+                    Def::Err => ParenthesizedGenericArgs::Ok,
+                    // An error
+                    Def::Struct(..) | Def::Enum(..) | Def::Union(..) | Def::TyAlias(..) |
+                    Def::Variant(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Err,
+                    // A warning for now, for compatibility reasons
+                    _ => ParenthesizedGenericArgs::Warn,
+                };
 
                 let num_lifetimes = type_def_id.map_or(0, |def_id| {
                     if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
@@ -757,7 +781,8 @@ impl<'a> LoweringContext<'a> {
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
-                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
+                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes,
+                                        parenthesized_generic_args)
             }).collect(),
             span: p.span,
         });
@@ -792,7 +817,8 @@ impl<'a> LoweringContext<'a> {
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
+            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0,
+                                                    ParenthesizedGenericArgs::Warn));
             let qpath = hir::QPath::TypeRelative(ty, segment);
 
             // It's finished, return the extension of the right node type.
@@ -825,7 +851,8 @@ impl<'a> LoweringContext<'a> {
         hir::Path {
             def: self.expect_full_def(id),
             segments: segments.map(|segment| {
-                self.lower_path_segment(p.span, segment, param_mode, 0)
+                self.lower_path_segment(p.span, segment, param_mode, 0,
+                                        ParenthesizedGenericArgs::Err)
             }).chain(name.map(|name| {
                 hir::PathSegment {
                     name,
@@ -849,29 +876,37 @@ impl<'a> LoweringContext<'a> {
                           path_span: Span,
                           segment: &PathSegment,
                           param_mode: ParamMode,
-                          expected_lifetimes: usize)
+                          expected_lifetimes: usize,
+                          parenthesized_generic_args: ParenthesizedGenericArgs)
                           -> hir::PathSegment {
         let mut parameters = if let Some(ref parameters) = segment.parameters {
+            let msg = "parenthesized parameters may only be used with a trait";
             match **parameters {
                 PathParameters::AngleBracketed(ref data) => {
-                    let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
-                    hir::AngleBracketedParameters(data)
+                    self.lower_angle_bracketed_parameter_data(data, param_mode)
                 }
-                PathParameters::Parenthesized(ref data) => {
-                    hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
+                PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
+                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Warn => {
+                        self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+                                              CRATE_NODE_ID, data.span, msg.into());
+                        hir::PathParameters::none()
+                    }
+                    ParenthesizedGenericArgs::Err => {
+                        struct_span_err!(self.sess, data.span, E0214, "{}", msg)
+                            .span_label(data.span, "only traits may use parentheses").emit();
+                        hir::PathParameters::none()
+                    }
                 }
             }
         } else {
-            let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
-            hir::AngleBracketedParameters(data)
+            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode)
         };
 
-        if let hir::AngleBracketedParameters(ref mut data) = parameters {
-            if data.lifetimes.is_empty() {
-                data.lifetimes = (0..expected_lifetimes).map(|_| {
-                    self.elided_lifetime(path_span)
-                }).collect();
-            }
+        if !parameters.parenthesized && parameters.lifetimes.is_empty() {
+            parameters.lifetimes = (0..expected_lifetimes).map(|_| {
+                self.elided_lifetime(path_span)
+            }).collect();
         }
 
         hir::PathSegment {
@@ -883,24 +918,38 @@ impl<'a> LoweringContext<'a> {
     fn lower_angle_bracketed_parameter_data(&mut self,
                                             data: &AngleBracketedParameterData,
                                             param_mode: ParamMode)
-                                            -> hir::AngleBracketedParameterData {
+                                            -> hir::PathParameters {
         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
-        hir::AngleBracketedParameterData {
+        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,
         }
     }
 
     fn lower_parenthesized_parameter_data(&mut self,
                                           data: &ParenthesizedParameterData)
-                                          -> hir::ParenthesizedParameterData {
+                                          -> hir::PathParameters {
         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
-        hir::ParenthesizedParameterData {
-            inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
-            output: output.as_ref().map(|ty| self.lower_ty(ty)),
-            span,
+        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 })
+        };
+
+        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),
+                ty: output.as_ref().map(|ty| self.lower_ty(&ty))
+                                   .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
+                span: output.as_ref().map_or(span, |ty| ty.span),
+            }],
+            parenthesized: true,
         }
     }
 
@@ -1266,7 +1315,12 @@ impl<'a> LoweringContext<'a> {
                             path.span = span;
 
                             self.allocate_hir_id_counter(import.id, import);
-                            self.with_hir_id_owner(import.id, |this| {
+                            let LoweredNodeId {
+                                node_id: import_node_id,
+                                hir_id: import_hir_id,
+                            } = self.lower_node_id(import.id);
+
+                            self.with_hir_id_owner(import_node_id, |this| {
                                 let vis = match *vis {
                                     hir::Visibility::Public => hir::Visibility::Public,
                                     hir::Visibility::Crate => hir::Visibility::Crate,
@@ -1280,8 +1334,9 @@ impl<'a> LoweringContext<'a> {
                                     }
                                 };
 
-                                this.items.insert(import.id, hir::Item {
-                                    id: import.id,
+                                this.items.insert(import_node_id, hir::Item {
+                                    id: import_node_id,
+                                    hir_id: import_hir_id,
                                     name: import.rename.unwrap_or(ident).name,
                                     attrs: attrs.clone(),
                                     node: hir::ItemUse(P(path), hir::UseKind::Single),
@@ -1412,8 +1467,11 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
         self.with_parent_def(i.id, |this| {
+            let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
             hir::TraitItem {
-                id: this.lower_node_id(i.id).node_id,
+                id: node_id,
+                hir_id,
                 name: this.lower_ident(i.ident),
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
@@ -1473,8 +1531,11 @@ impl<'a> LoweringContext<'a> {
 
     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         self.with_parent_def(i.id, |this| {
+            let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
             hir::ImplItem {
-                id: this.lower_node_id(i.id).node_id,
+                id: node_id,
+                hir_id,
                 name: this.lower_ident(i.ident),
                 attrs: this.lower_attrs(&i.attrs),
                 vis: this.lower_visibility(&i.vis, None),
@@ -1565,8 +1626,11 @@ impl<'a> LoweringContext<'a> {
             this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
         });
 
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
+
         Some(hir::Item {
-            id: self.lower_node_id(i.id).node_id,
+            id: node_id,
+            hir_id,
             name,
             attrs,
             node,
@@ -1790,7 +1854,8 @@ impl<'a> LoweringContext<'a> {
                 let move_val_init = ["intrinsics", "move_val_init"];
                 let inplace_finalize = ["ops", "InPlace", "finalize"];
 
-                let unstable_span = self.allow_internal_unstable("<-", e.span);
+                let unstable_span =
+                    self.allow_internal_unstable(CompilerDesugaringKind::BackArrow, e.span);
                 let make_call = |this: &mut LoweringContext, p, args| {
                     let path = P(this.expr_std_path(unstable_span, p, ThinVec::new()));
                     P(this.expr_call(e.span, path, args))
@@ -1874,7 +1939,8 @@ impl<'a> LoweringContext<'a> {
                 hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
+                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0,
+                                                      ParenthesizedGenericArgs::Err);
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
                 hir::ExprMethodCall(hir_seg, seg.span, args)
             }
@@ -2007,12 +2073,14 @@ impl<'a> LoweringContext<'a> {
                     e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e)))
                     .map(|(s, e)| {
                         let expr = P(self.lower_expr(&e));
-                        let unstable_span = self.allow_internal_unstable("...", e.span);
+                        let unstable_span =
+                            self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                         self.field(Symbol::intern(s), expr, unstable_span)
                     }).collect::<P<[hir::Field]>>();
 
                 let is_unit = fields.is_empty();
-                let unstable_span = self.allow_internal_unstable("...", e.span);
+                let unstable_span =
+                    self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                 let struct_path =
                     iter::once("ops").chain(iter::once(path))
                     .collect::<Vec<_>>();
@@ -2353,7 +2421,8 @@ impl<'a> LoweringContext<'a> {
                 //                 return Try::from_error(From::from(err)),
                 // }
 
-                let unstable_span = self.allow_internal_unstable("?", e.span);
+                let unstable_span =
+                    self.allow_internal_unstable(CompilerDesugaringKind::QuestionMark, e.span);
 
                 // Try::into_result(<expr>)
                 let discr = {
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index d3ae3e0e8e8..a54068c6483 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -10,33 +10,55 @@
 
 use super::*;
 
+use dep_graph::{DepGraph, DepKind, DepNodeIndex};
 use hir::intravisit::{Visitor, NestedVisitorMap};
 use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax_pos::Span;
 
 /// A Visitor that walks over the HIR and collects Nodes into a HIR map
-pub struct NodeCollector<'hir> {
+pub(super) struct NodeCollector<'a, 'hir> {
     /// The crate
-    pub krate: &'hir Crate,
+    krate: &'hir Crate,
     /// The node map
-    pub(super) map: Vec<MapEntry<'hir>>,
+    map: Vec<MapEntry<'hir>>,
     /// The parent of this node
-    pub parent_node: NodeId,
+    parent_node: NodeId,
+
+    current_dep_node_owner: DefIndex,
+    current_dep_node_index: DepNodeIndex,
+
+    dep_graph: &'a DepGraph,
+    definitions: &'a definitions::Definitions,
 }
 
-impl<'hir> NodeCollector<'hir> {
-    pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> {
+impl<'a, 'hir> NodeCollector<'a, 'hir> {
+    pub(super) fn root(krate: &'hir Crate,
+                dep_graph: &'a DepGraph,
+                definitions: &'a definitions::Definitions)
+                -> 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);
+
         let mut collector = NodeCollector {
             krate,
             map: vec![],
             parent_node: CRATE_NODE_ID,
+            current_dep_node_index: root_mod_dep_node_index,
+            current_dep_node_owner: CRATE_DEF_INDEX,
+            dep_graph,
+            definitions,
         };
-        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+        collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index));
 
         collector
     }
 
+    pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> {
+        self.map
+    }
+
     fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
         debug!("hir_map: {:?} => {:?}", id, entry);
         let len = self.map.len();
@@ -47,8 +69,55 @@ impl<'hir> NodeCollector<'hir> {
     }
 
     fn insert(&mut self, id: NodeId, node: Node<'hir>) {
-        let entry = MapEntry::from_node(self.parent_node, node);
+        let parent = self.parent_node;
+        let dep_node_index = self.current_dep_node_index;
+
+        let entry = match node {
+            NodeItem(n) => EntryItem(parent, dep_node_index, n),
+            NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n),
+            NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n),
+            NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
+            NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
+            NodeField(n) => EntryField(parent, dep_node_index, n),
+            NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
+            NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
+            NodeTy(n) => EntryTy(parent, dep_node_index, n),
+            NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n),
+            NodeBinding(n) => EntryBinding(parent, dep_node_index, n),
+            NodePat(n) => EntryPat(parent, dep_node_index, n),
+            NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
+            NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
+            NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
+            NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
+            NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
+            NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
+        };
+
+        // Make sure that the DepNode of some node coincides with the HirId
+        // owner of that node.
+        if cfg!(debug_assertions) {
+            let hir_id_owner = self.definitions.node_to_hir_id(id).owner;
+
+            if hir_id_owner != self.current_dep_node_owner {
+                let node_str = match self.definitions.opt_def_index(id) {
+                    Some(def_index) => {
+                        self.definitions.def_path(def_index).to_string_no_crate()
+                    }
+                    None => format!("{:?}", node)
+                };
+
+                bug!("inconsistent DepNode for `{}`: \
+                      current_dep_node_owner={}, hir_id.owner={}",
+                    node_str,
+                    self.definitions
+                        .def_path(self.current_dep_node_owner)
+                        .to_string_no_crate(),
+                    self.definitions.def_path(hir_id_owner).to_string_no_crate())
+            }
+        }
+
         self.insert_entry(id, entry);
+
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
@@ -57,9 +126,27 @@ impl<'hir> NodeCollector<'hir> {
         f(self);
         self.parent_node = parent_node;
     }
+
+    fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self,
+                                                 dep_node_owner: DefIndex,
+                                                 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);
+        self.current_dep_node_owner = dep_node_owner;
+        f(self);
+        self.current_dep_node_index = prev_index;
+        self.current_dep_node_owner = prev_owner;
+    }
 }
 
-impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
+impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     /// Because we want to track parent items and so forth, enable
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
@@ -82,25 +169,37 @@ impl<'hir> Visitor<'hir> for NodeCollector<'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);
         self.visit_body(self.krate.body(id));
+        self.current_dep_node_index = prev_index;
     }
 
     fn visit_item(&mut self, i: &'hir Item) {
         debug!("visit_item: {:?}", i);
-
-        self.insert(i.id, NodeItem(i));
-
-        self.with_parent(i.id, |this| {
-            match i.node {
-                ItemStruct(ref struct_def, _) => {
-                    // If this is a tuple-like struct, register the constructor.
-                    if !struct_def.is_struct() {
-                        this.insert(struct_def.id(), NodeStructCtor(struct_def));
+        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| {
+            this.insert(i.id, NodeItem(i));
+            this.with_parent(i.id, |this| {
+                match i.node {
+                    ItemStruct(ref struct_def, _) => {
+                        // If this is a tuple-like struct, register the constructor.
+                        if !struct_def.is_struct() {
+                            this.insert(struct_def.id(), NodeStructCtor(struct_def));
+                        }
                     }
+                    _ => {}
                 }
-                _ => {}
-            }
-            intravisit::walk_item(this, i);
+                intravisit::walk_item(this, i);
+            });
         });
     }
 
@@ -121,24 +220,32 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
     }
 
     fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
-        self.insert(ti.id, NodeTraitItem(ti));
-
-        self.with_parent(ti.id, |this| {
-            intravisit::walk_trait_item(this, ti);
+        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| {
+            this.insert(ti.id, NodeTraitItem(ti));
+
+            this.with_parent(ti.id, |this| {
+                intravisit::walk_trait_item(this, ti);
+            });
         });
     }
 
     fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
-        self.insert(ii.id, NodeImplItem(ii));
-
-        self.with_parent(ii.id, |this| {
-            intravisit::walk_impl_item(this, ii);
+        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| {
+            this.insert(ii.id, NodeImplItem(ii));
+
+            this.with_parent(ii.id, |this| {
+                intravisit::walk_impl_item(this, ii);
+            });
         });
     }
 
     fn visit_pat(&mut self, pat: &'hir Pat) {
         let node = if let PatKind::Binding(..) = pat.node {
-            NodeLocal(pat)
+            NodeBinding(pat)
         } else {
             NodePat(pat)
         };
@@ -195,6 +302,13 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
         });
     }
 
+    fn visit_local(&mut self, l: &'hir Local) {
+        self.insert(l.id, NodeLocal(l));
+        self.with_parent(l.id, |this| {
+            intravisit::walk_local(this, l)
+        })
+    }
+
     fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) {
         self.insert(lifetime.id, NodeLifetime(lifetime));
     }
@@ -231,4 +345,33 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
             intravisit::walk_struct_field(this, field);
         });
     }
+
+    fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
+        // Do not visit the duplicate information in TraitItemRef. We want to
+        // map the actual nodes, not the duplicate ones in the *Ref.
+        let TraitItemRef {
+            id,
+            name: _,
+            kind: _,
+            span: _,
+            defaultness: _,
+        } = *ii;
+
+        self.visit_nested_trait_item(id);
+    }
+
+    fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
+        // Do not visit the duplicate information in ImplItemRef. We want to
+        // map the actual nodes, not the duplicate ones in the *Ref.
+        let ImplItemRef {
+            id,
+            name: _,
+            kind: _,
+            span: _,
+            vis: _,
+            defaultness: _,
+        } = *ii;
+
+        self.visit_nested_impl_item(id);
+    }
 }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index ed4e28cc9eb..63a5b70cb81 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -15,7 +15,7 @@ pub use self::def_collector::{DefCollector, MacroInvocationData};
 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
                             DisambiguatedDefPathData, DefPathHash};
 
-use dep_graph::{DepGraph, DepNode, DepKind};
+use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
 
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace};
 
@@ -53,9 +53,10 @@ pub enum Node<'hir> {
     NodeStmt(&'hir Stmt),
     NodeTy(&'hir Ty),
     NodeTraitRef(&'hir TraitRef),
-    NodeLocal(&'hir Pat),
+    NodeBinding(&'hir Pat),
     NodePat(&'hir Pat),
     NodeBlock(&'hir Block),
+    NodeLocal(&'hir Local),
 
     /// NodeStructCtor represents a tuple struct.
     NodeStructCtor(&'hir VariantData),
@@ -73,26 +74,28 @@ enum MapEntry<'hir> {
     NotPresent,
 
     /// All the node types, with a parent ID.
-    EntryItem(NodeId, &'hir Item),
-    EntryForeignItem(NodeId, &'hir ForeignItem),
-    EntryTraitItem(NodeId, &'hir TraitItem),
-    EntryImplItem(NodeId, &'hir ImplItem),
-    EntryVariant(NodeId, &'hir Variant),
-    EntryField(NodeId, &'hir StructField),
-    EntryExpr(NodeId, &'hir Expr),
-    EntryStmt(NodeId, &'hir Stmt),
-    EntryTy(NodeId, &'hir Ty),
-    EntryTraitRef(NodeId, &'hir TraitRef),
-    EntryLocal(NodeId, &'hir Pat),
-    EntryPat(NodeId, &'hir Pat),
-    EntryBlock(NodeId, &'hir Block),
-    EntryStructCtor(NodeId, &'hir VariantData),
-    EntryLifetime(NodeId, &'hir Lifetime),
-    EntryTyParam(NodeId, &'hir TyParam),
-    EntryVisibility(NodeId, &'hir Visibility),
-
-    /// Roots for node trees.
-    RootCrate,
+    EntryItem(NodeId, DepNodeIndex, &'hir Item),
+    EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem),
+    EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem),
+    EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
+    EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
+    EntryField(NodeId, DepNodeIndex, &'hir StructField),
+    EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
+    EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
+    EntryTy(NodeId, DepNodeIndex, &'hir Ty),
+    EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef),
+    EntryBinding(NodeId, DepNodeIndex, &'hir Pat),
+    EntryPat(NodeId, DepNodeIndex, &'hir Pat),
+    EntryBlock(NodeId, DepNodeIndex, &'hir Block),
+    EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
+    EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
+    EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam),
+    EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
+    EntryLocal(NodeId, DepNodeIndex, &'hir Local),
+
+    /// Roots for node trees. The DepNodeIndex is the dependency node of the
+    /// crate's root module.
+    RootCrate(DepNodeIndex),
 }
 
 impl<'hir> Clone for MapEntry<'hir> {
@@ -102,79 +105,59 @@ impl<'hir> Clone for MapEntry<'hir> {
 }
 
 impl<'hir> MapEntry<'hir> {
-    fn from_node(p: NodeId, node: Node<'hir>) -> MapEntry<'hir> {
-        match node {
-            NodeItem(n) => EntryItem(p, n),
-            NodeForeignItem(n) => EntryForeignItem(p, n),
-            NodeTraitItem(n) => EntryTraitItem(p, n),
-            NodeImplItem(n) => EntryImplItem(p, n),
-            NodeVariant(n) => EntryVariant(p, n),
-            NodeField(n) => EntryField(p, n),
-            NodeExpr(n) => EntryExpr(p, n),
-            NodeStmt(n) => EntryStmt(p, n),
-            NodeTy(n) => EntryTy(p, n),
-            NodeTraitRef(n) => EntryTraitRef(p, n),
-            NodeLocal(n) => EntryLocal(p, n),
-            NodePat(n) => EntryPat(p, n),
-            NodeBlock(n) => EntryBlock(p, n),
-            NodeStructCtor(n) => EntryStructCtor(p, n),
-            NodeLifetime(n) => EntryLifetime(p, n),
-            NodeTyParam(n) => EntryTyParam(p, n),
-            NodeVisibility(n) => EntryVisibility(p, n),
-        }
-    }
-
     fn parent_node(self) -> Option<NodeId> {
         Some(match self {
-            EntryItem(id, _) => id,
-            EntryForeignItem(id, _) => id,
-            EntryTraitItem(id, _) => id,
-            EntryImplItem(id, _) => id,
-            EntryVariant(id, _) => id,
-            EntryField(id, _) => id,
-            EntryExpr(id, _) => id,
-            EntryStmt(id, _) => id,
-            EntryTy(id, _) => id,
-            EntryTraitRef(id, _) => id,
-            EntryLocal(id, _) => id,
-            EntryPat(id, _) => id,
-            EntryBlock(id, _) => id,
-            EntryStructCtor(id, _) => id,
-            EntryLifetime(id, _) => id,
-            EntryTyParam(id, _) => id,
-            EntryVisibility(id, _) => id,
+            EntryItem(id, _, _) => id,
+            EntryForeignItem(id, _, _) => id,
+            EntryTraitItem(id, _, _) => id,
+            EntryImplItem(id, _, _) => id,
+            EntryVariant(id, _, _) => id,
+            EntryField(id, _, _) => id,
+            EntryExpr(id, _, _) => id,
+            EntryStmt(id, _, _) => id,
+            EntryTy(id, _, _) => id,
+            EntryTraitRef(id, _, _) => id,
+            EntryBinding(id, _, _) => id,
+            EntryPat(id, _, _) => id,
+            EntryBlock(id, _, _) => id,
+            EntryStructCtor(id, _, _) => id,
+            EntryLifetime(id, _, _) => id,
+            EntryTyParam(id, _, _) => id,
+            EntryVisibility(id, _, _) => id,
+            EntryLocal(id, _, _) => id,
 
             NotPresent |
-            RootCrate => return None,
+            RootCrate(_) => return None,
         })
     }
 
     fn to_node(self) -> Option<Node<'hir>> {
         Some(match self {
-            EntryItem(_, n) => NodeItem(n),
-            EntryForeignItem(_, n) => NodeForeignItem(n),
-            EntryTraitItem(_, n) => NodeTraitItem(n),
-            EntryImplItem(_, n) => NodeImplItem(n),
-            EntryVariant(_, n) => NodeVariant(n),
-            EntryField(_, n) => NodeField(n),
-            EntryExpr(_, n) => NodeExpr(n),
-            EntryStmt(_, n) => NodeStmt(n),
-            EntryTy(_, n) => NodeTy(n),
-            EntryTraitRef(_, n) => NodeTraitRef(n),
-            EntryLocal(_, n) => NodeLocal(n),
-            EntryPat(_, n) => NodePat(n),
-            EntryBlock(_, n) => NodeBlock(n),
-            EntryStructCtor(_, n) => NodeStructCtor(n),
-            EntryLifetime(_, n) => NodeLifetime(n),
-            EntryTyParam(_, n) => NodeTyParam(n),
-            EntryVisibility(_, n) => NodeVisibility(n),
+            EntryItem(_, _, n) => NodeItem(n),
+            EntryForeignItem(_, _, n) => NodeForeignItem(n),
+            EntryTraitItem(_, _, n) => NodeTraitItem(n),
+            EntryImplItem(_, _, n) => NodeImplItem(n),
+            EntryVariant(_, _, n) => NodeVariant(n),
+            EntryField(_, _, n) => NodeField(n),
+            EntryExpr(_, _, n) => NodeExpr(n),
+            EntryStmt(_, _, n) => NodeStmt(n),
+            EntryTy(_, _, n) => NodeTy(n),
+            EntryTraitRef(_, _, n) => NodeTraitRef(n),
+            EntryBinding(_, _, n) => NodeBinding(n),
+            EntryPat(_, _, n) => NodePat(n),
+            EntryBlock(_, _, n) => NodeBlock(n),
+            EntryStructCtor(_, _, n) => NodeStructCtor(n),
+            EntryLifetime(_, _, n) => NodeLifetime(n),
+            EntryTyParam(_, _, n) => NodeTyParam(n),
+            EntryVisibility(_, _, n) => NodeVisibility(n),
+            EntryLocal(_, _, n) => NodeLocal(n),
             _ => return None
         })
     }
 
     fn associated_body(self) -> Option<BodyId> {
         match self {
-            EntryItem(_, item) => {
+            EntryItem(_, _, item) => {
                 match item.node {
                     ItemConst(_, body) |
                     ItemStatic(.., body) |
@@ -183,7 +166,7 @@ impl<'hir> MapEntry<'hir> {
                 }
             }
 
-            EntryTraitItem(_, item) => {
+            EntryTraitItem(_, _, item) => {
                 match item.node {
                     TraitItemKind::Const(_, Some(body)) |
                     TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
@@ -191,7 +174,7 @@ impl<'hir> MapEntry<'hir> {
                 }
             }
 
-            EntryImplItem(_, item) => {
+            EntryImplItem(_, _, item) => {
                 match item.node {
                     ImplItemKind::Const(_, body) |
                     ImplItemKind::Method(_, body) => Some(body),
@@ -199,7 +182,7 @@ impl<'hir> MapEntry<'hir> {
                 }
             }
 
-            EntryExpr(_, expr) => {
+            EntryExpr(_, _, expr) => {
                 match expr.node {
                     ExprClosure(.., body, _) => Some(body),
                     _ => None,
@@ -277,82 +260,40 @@ impl<'hir> Map<'hir> {
     /// read recorded). If the function just returns a DefId or
     /// NodeId, no actual content was returned, so no read is needed.
     pub fn read(&self, id: NodeId) {
-        self.dep_graph.read(self.dep_node(id));
-    }
-
-    fn dep_node(&self, id0: NodeId) -> DepNode {
-        let mut id = id0;
-        let mut last_expr = None;
-        loop {
-            let entry = self.map[id.as_usize()];
-            match entry {
-                EntryItem(..) |
-                EntryTraitItem(..) |
-                EntryImplItem(..) => {
-                    let def_index = self.definitions.opt_def_index(id).unwrap();
+        let entry = self.map[id.as_usize()];
+        match entry {
+            EntryItem(_, dep_node_index, _) |
+            EntryTraitItem(_, dep_node_index, _) |
+            EntryImplItem(_, dep_node_index, _) |
+            EntryVariant(_, dep_node_index, _) |
+            EntryForeignItem(_, dep_node_index, _) |
+            EntryField(_, dep_node_index, _) |
+            EntryStmt(_, dep_node_index, _) |
+            EntryTy(_, dep_node_index, _) |
+            EntryTraitRef(_, dep_node_index, _) |
+            EntryBinding(_, dep_node_index, _) |
+            EntryPat(_, dep_node_index, _) |
+            EntryBlock(_, dep_node_index, _) |
+            EntryStructCtor(_, dep_node_index, _) |
+            EntryLifetime(_, dep_node_index, _) |
+            EntryTyParam(_, dep_node_index, _) |
+            EntryVisibility(_, dep_node_index, _) |
+            EntryExpr(_, dep_node_index, _) |
+            EntryLocal(_, 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);
-
-                    if let Some(last_id) = last_expr {
-                        // The body may have a separate dep node
-                        if entry.is_body_owner(last_id) {
-                            return def_path_hash.to_dep_node(DepKind::HirBody);
-                        }
-                    }
-                    return def_path_hash.to_dep_node(DepKind::Hir);
-                }
-
-                EntryVariant(p, v) => {
-                    id = p;
-
-                    if last_expr.is_some() {
-                        if v.node.disr_expr.map(|e| e.node_id) == last_expr {
-                            // The enum parent holds both Hir and HirBody nodes.
-                            let def_index = self.definitions.opt_def_index(id).unwrap();
-                            let def_path_hash = self.definitions.def_path_hash(def_index);
-                            return def_path_hash.to_dep_node(DepKind::HirBody);
-                        }
-                    }
-                }
-
-                EntryForeignItem(p, _) |
-                EntryField(p, _) |
-                EntryStmt(p, _) |
-                EntryTy(p, _) |
-                EntryTraitRef(p, _) |
-                EntryLocal(p, _) |
-                EntryPat(p, _) |
-                EntryBlock(p, _) |
-                EntryStructCtor(p, _) |
-                EntryLifetime(p, _) |
-                EntryTyParam(p, _) |
-                EntryVisibility(p, _) =>
-                    id = p,
-
-                EntryExpr(p, _) => {
-                    last_expr = Some(id);
-                    id = p;
-                }
-
-                RootCrate => {
-                    let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
-                    return def_path_hash.to_dep_node(DepKind::Hir);
+                    self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+                } else {
+                    bug!("called HirMap::read() with invalid NodeId")
                 }
-
-                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.
-                    return self.definitions.opt_def_index(id)
-                               .map(|def_index| {
-                                    let def_path_hash = self.definitions.def_path_hash(def_index);
-                                    def_path_hash.to_dep_node(DepKind::Hir)
-                                })
-                               .unwrap_or_else(|| {
-                                   bug!("Walking parents from `{}` \
-                                         led to `NotPresent` at `{}`",
-                                        id0, id)
-                               }),
             }
         }
     }
@@ -475,7 +416,7 @@ impl<'hir> Map<'hir> {
                 Some(body_id)
             } else {
                 // For some expressions, the expression is its own body.
-                if let EntryExpr(_, expr) = entry {
+                if let EntryExpr(_, _, expr) = entry {
                     Some(BodyId { node_id: expr.id })
                 } else {
                     None
@@ -589,7 +530,7 @@ impl<'hir> Map<'hir> {
     /// immediate parent is an item or a closure.
     pub fn is_argument(&self, id: NodeId) -> bool {
         match self.find(id) {
-            Some(NodeLocal(_)) => (),
+            Some(NodeBinding(_)) => (),
             _ => return false,
         }
         match self.find(self.get_parent_node(id)) {
@@ -731,7 +672,7 @@ impl<'hir> Map<'hir> {
 
     /// Returns the nearest enclosing scope. A scope is an item or block.
     /// FIXME it is not clear to me that all items qualify as scopes - statics
-    /// and associated types probably shouldn't, for example. Behaviour in this
+    /// and associated types probably shouldn't, for example. Behavior in this
     /// regard should be expected to be highly unstable.
     pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
         match self.walk_parent_nodes(id, |node| match *node {
@@ -754,7 +695,7 @@ impl<'hir> Map<'hir> {
     pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
         let parent = self.get_parent(id);
         let abi = match self.find_entry(parent) {
-            Some(EntryItem(_, i)) => {
+            Some(EntryItem(_, _, i)) => {
                 match i.node {
                     ItemForeignMod(ref nm) => Some(nm.abi),
                     _ => None
@@ -856,7 +797,7 @@ impl<'hir> Map<'hir> {
             NodeField(f) => f.name,
             NodeLifetime(lt) => lt.name,
             NodeTyParam(tp) => tp.name,
-            NodeLocal(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
+            NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
             NodeStructCtor(_) => self.name(self.get_parent(id)),
             _ => bug!("no name for {}", self.node_to_string(id))
         }
@@ -905,26 +846,27 @@ impl<'hir> Map<'hir> {
     pub fn span(&self, id: NodeId) -> Span {
         self.read(id); // reveals span from node
         match self.find_entry(id) {
-            Some(EntryItem(_, item)) => item.span,
-            Some(EntryForeignItem(_, foreign_item)) => foreign_item.span,
-            Some(EntryTraitItem(_, trait_method)) => trait_method.span,
-            Some(EntryImplItem(_, impl_item)) => impl_item.span,
-            Some(EntryVariant(_, variant)) => variant.span,
-            Some(EntryField(_, field)) => field.span,
-            Some(EntryExpr(_, expr)) => expr.span,
-            Some(EntryStmt(_, stmt)) => stmt.span,
-            Some(EntryTy(_, ty)) => ty.span,
-            Some(EntryTraitRef(_, tr)) => tr.path.span,
-            Some(EntryLocal(_, pat)) => pat.span,
-            Some(EntryPat(_, pat)) => pat.span,
-            Some(EntryBlock(_, block)) => block.span,
-            Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span,
-            Some(EntryLifetime(_, lifetime)) => lifetime.span,
-            Some(EntryTyParam(_, ty_param)) => ty_param.span,
-            Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span,
-            Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
-
-            Some(RootCrate) => self.forest.krate.span,
+            Some(EntryItem(_, _, item)) => item.span,
+            Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span,
+            Some(EntryTraitItem(_, _, trait_method)) => trait_method.span,
+            Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
+            Some(EntryVariant(_, _, variant)) => variant.span,
+            Some(EntryField(_, _, field)) => field.span,
+            Some(EntryExpr(_, _, expr)) => expr.span,
+            Some(EntryStmt(_, _, stmt)) => stmt.span,
+            Some(EntryTy(_, _, ty)) => ty.span,
+            Some(EntryTraitRef(_, _, tr)) => tr.path.span,
+            Some(EntryBinding(_, _, pat)) => pat.span,
+            Some(EntryPat(_, _, pat)) => pat.span,
+            Some(EntryBlock(_, _, block)) => block.span,
+            Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
+            Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
+            Some(EntryTyParam(_, _, ty_param)) => ty_param.span,
+            Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
+            Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
+            Some(EntryLocal(_, _, local)) => local.span,
+
+            Some(RootCrate(_)) => self.forest.krate.span,
             Some(NotPresent) | None => {
                 bug!("hir::map::Map::span: id not in map: {:?}", id)
             }
@@ -1022,12 +964,12 @@ impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> {
             }
             self.idx = NodeId::from_u32(self.idx.as_u32() + 1);
             let name = match self.map.find_entry(idx) {
-                Some(EntryItem(_, n))       => n.name(),
-                Some(EntryForeignItem(_, n))=> n.name(),
-                Some(EntryTraitItem(_, n))  => n.name(),
-                Some(EntryImplItem(_, n))   => n.name(),
-                Some(EntryVariant(_, n))    => n.name(),
-                Some(EntryField(_, n))      => n.name(),
+                Some(EntryItem(_, _, n))       => n.name(),
+                Some(EntryForeignItem(_, _, n))=> n.name(),
+                Some(EntryTraitItem(_, _, n))  => n.name(),
+                Some(EntryImplItem(_, _, n))   => n.name(),
+                Some(EntryVariant(_, _, n))    => n.name(),
+                Some(EntryField(_, _, n))      => n.name(),
                 _ => continue,
             };
             if self.matches_names(self.map.get_parent(idx), name) {
@@ -1053,9 +995,13 @@ impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 pub fn map_crate<'hir>(forest: &'hir mut Forest,
                        definitions: Definitions)
                        -> Map<'hir> {
-    let mut collector = NodeCollector::root(&forest.krate);
-    intravisit::walk_crate(&mut collector, &forest.krate);
-    let map = collector.map;
+    let map = {
+        let mut collector = NodeCollector::root(&forest.krate,
+                                                &forest.dep_graph,
+                                                &definitions);
+        intravisit::walk_crate(&mut collector, &forest.krate);
+        collector.into_map()
+    };
 
     if log_enabled!(::log::LogLevel::Debug) {
         // This only makes sense for ordered stores; note the
@@ -1112,7 +1058,7 @@ impl<'a> print::State<'a> {
             NodeStmt(a)        => self.print_stmt(&a),
             NodeTy(a)          => self.print_type(&a),
             NodeTraitRef(a)    => self.print_trait_ref(&a),
-            NodeLocal(a)       |
+            NodeBinding(a)       |
             NodePat(a)         => self.print_pat(&a),
             NodeBlock(a)       => {
                 use syntax::print::pprust::PrintState;
@@ -1131,6 +1077,7 @@ impl<'a> print::State<'a> {
             // hir_map to reconstruct their full structure for pretty
             // printing.
             NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
+            NodeLocal(a)       => self.print_local_decl(&a),
         }
     }
 }
@@ -1223,7 +1170,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeTraitRef(_)) => {
             format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(NodeLocal(_)) => {
+        Some(NodeBinding(_)) => {
             format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
         Some(NodePat(_)) => {
@@ -1232,6 +1179,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeBlock(_)) => {
             format!("block {}{}", map.node_to_pretty_string(id), id_str)
         }
+        Some(NodeLocal(_)) => {
+            format!("local {}{}", map.node_to_pretty_string(id), id_str)
+        }
         Some(NodeStructCtor(_)) => {
             format!("struct_ctor {}{}", path_str(), id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 3806b517f77..df67f841621 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -26,7 +26,6 @@ pub use self::TyParamBound::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 pub use self::Visibility::{Public, Inherited};
-pub use self::PathParameters::*;
 
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
@@ -42,6 +41,7 @@ use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
 use syntax::util::ThinVec;
+use ty::AdtKind;
 
 use rustc_data_structures::indexed_vec;
 
@@ -226,65 +226,7 @@ impl PathSegment {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum PathParameters {
-    /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
-    AngleBracketedParameters(AngleBracketedParameterData),
-    /// The `(A,B)` and `C` in `Foo(A,B) -> C`
-    ParenthesizedParameters(ParenthesizedParameterData),
-}
-
-impl PathParameters {
-    pub fn none() -> PathParameters {
-        AngleBracketedParameters(AngleBracketedParameterData {
-            lifetimes: HirVec::new(),
-            types: HirVec::new(),
-            infer_types: true,
-            bindings: HirVec::new(),
-        })
-    }
-
-    /// Returns the types that the user wrote. Note that these do not necessarily map to the type
-    /// parameters in the parenthesized case.
-    pub fn types(&self) -> HirVec<&P<Ty>> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.types.iter().collect()
-            }
-            ParenthesizedParameters(ref data) => {
-                data.inputs
-                    .iter()
-                    .chain(data.output.iter())
-                    .collect()
-            }
-        }
-    }
-
-    pub fn lifetimes(&self) -> HirVec<&Lifetime> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.lifetimes.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-
-    pub fn bindings(&self) -> HirVec<&TypeBinding> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.bindings.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-}
-
-/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct AngleBracketedParameterData {
+pub struct PathParameters {
     /// The lifetime parameters for this path segment.
     pub lifetimes: HirVec<Lifetime>,
     /// The type parameters for this path segment, if present.
@@ -297,19 +239,33 @@ pub struct AngleBracketedParameterData {
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
+    /// Were parameters written in parenthesized form `Fn(T) -> U`?
+    /// This is required mostly for pretty-printing and diagnostics,
+    /// but also for changing lifetime elision rules to be "function-like".
+    pub parenthesized: bool,
 }
 
-/// A path like `Foo(A,B) -> C`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ParenthesizedParameterData {
-    /// Overall span
-    pub span: Span,
-
-    /// `(A,B)`
-    pub inputs: HirVec<P<Ty>>,
+impl PathParameters {
+    pub fn none() -> Self {
+        Self {
+            lifetimes: HirVec::new(),
+            types: HirVec::new(),
+            infer_types: true,
+            bindings: HirVec::new(),
+            parenthesized: false,
+        }
+    }
 
-    /// `C`
-    pub output: Option<P<Ty>>,
+    pub fn inputs(&self) -> &[P<Ty>] {
+        if self.parenthesized {
+            if let Some(ref ty) = self.types.get(0) {
+                if let TyTup(ref tys) = ty.node {
+                    return tys;
+                }
+            }
+        }
+        bug!("PathParameters::inputs: not a `Fn(T) -> U`");
+    }
 }
 
 /// The AST represents all type param bounds as types.
@@ -1264,6 +1220,7 @@ pub struct TraitItemId {
 pub struct TraitItem {
     pub id: NodeId,
     pub name: Name,
+    pub hir_id: HirId,
     pub attrs: HirVec<Attribute>,
     pub node: TraitItemKind,
     pub span: Span,
@@ -1305,6 +1262,7 @@ pub struct ImplItemId {
 pub struct ImplItem {
     pub id: NodeId,
     pub name: Name,
+    pub hir_id: HirId,
     pub vis: Visibility,
     pub defaultness: Defaultness,
     pub attrs: HirVec<Attribute>,
@@ -1711,8 +1669,9 @@ pub struct ItemId {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Item {
     pub name: Name,
-    pub attrs: HirVec<Attribute>,
     pub id: NodeId,
+    pub hir_id: HirId,
+    pub attrs: HirVec<Attribute>,
     pub node: Item_,
     pub vis: Visibility,
     pub span: Span,
@@ -1789,6 +1748,15 @@ impl Item_ {
             ItemDefaultImpl(..) => "item",
         }
     }
+
+    pub fn adt_kind(&self) -> Option<AdtKind> {
+        match *self {
+            ItemStruct(..) => Some(AdtKind::Struct),
+            ItemUnion(..) => Some(AdtKind::Union),
+            ItemEnum(..) => Some(AdtKind::Enum),
+            _ => None,
+        }
+    }
 }
 
 /// A reference from an trait to one of its associated items. This
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index abfb00a24a1..876875bce4a 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1194,9 +1194,9 @@ impl<'a> State<'a> {
         self.print_expr(&args[0])?;
         self.s.word(".")?;
         self.print_name(segment.name)?;
-        if !segment.parameters.lifetimes().is_empty() ||
-                !segment.parameters.types().is_empty() ||
-                !segment.parameters.bindings().is_empty() {
+        if !segment.parameters.lifetimes.is_empty() ||
+                !segment.parameters.types.is_empty() ||
+                !segment.parameters.bindings.is_empty() {
             self.print_path_parameters(&segment.parameters, true)?;
         }
         self.print_call_post(base_args)
@@ -1581,61 +1581,55 @@ impl<'a> State<'a> {
                              parameters: &hir::PathParameters,
                              colons_before_params: bool)
                              -> io::Result<()> {
-        match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                let start = if colons_before_params { "::<" } else { "<" };
-                let empty = Cell::new(true);
-                let start_or_comma = |this: &mut Self| {
-                    if empty.get() {
-                        empty.set(false);
-                        this.s.word(start)
-                    } else {
-                        this.word_space(",")
-                    }
-                };
+        if parameters.parenthesized {
+            self.s.word("(")?;
+            self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+            self.s.word(")")?;
 
-                if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                    for lifetime in &data.lifetimes {
-                        start_or_comma(self)?;
-                        self.print_lifetime(lifetime)?;
-                    }
-                }
-
-                if !data.types.is_empty() {
-                    start_or_comma(self)?;
-                    self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
+            self.space_if_not_bol()?;
+            self.word_space("->")?;
+            self.print_type(&parameters.bindings[0].ty)?;
+        } else {
+            let start = if colons_before_params { "::<" } else { "<" };
+            let empty = Cell::new(true);
+            let start_or_comma = |this: &mut Self| {
+                if empty.get() {
+                    empty.set(false);
+                    this.s.word(start)
+                } else {
+                    this.word_space(",")
                 }
+            };
 
-                // FIXME(eddyb) This would leak into error messages, e.g.:
-                // "non-exhaustive patterns: `Some::<..>(_)` not covered".
-                if data.infer_types && false {
+            if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
+                for lifetime in &parameters.lifetimes {
                     start_or_comma(self)?;
-                    self.s.word("..")?;
+                    self.print_lifetime(lifetime)?;
                 }
+            }
 
-                for binding in data.bindings.iter() {
-                    start_or_comma(self)?;
-                    self.print_name(binding.name)?;
-                    self.s.space()?;
-                    self.word_space("=")?;
-                    self.print_type(&binding.ty)?;
-                }
+            if !parameters.types.is_empty() {
+                start_or_comma(self)?;
+                self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
+            }
 
-                if !empty.get() {
-                    self.s.word(">")?
-                }
+            // FIXME(eddyb) This would leak into error messages, e.g.:
+            // "non-exhaustive patterns: `Some::<..>(_)` not covered".
+            if parameters.infer_types && false {
+                start_or_comma(self)?;
+                self.s.word("..")?;
             }
 
-            hir::ParenthesizedParameters(ref data) => {
-                self.s.word("(")?;
-                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
-                self.s.word(")")?;
+            for binding in parameters.bindings.iter() {
+                start_or_comma(self)?;
+                self.print_name(binding.name)?;
+                self.s.space()?;
+                self.word_space("=")?;
+                self.print_type(&binding.ty)?;
+            }
 
-                if let Some(ref ty) = data.output {
-                    self.space_if_not_bol()?;
-                    self.word_space("->")?;
-                    self.print_type(&ty)?;
-                }
+            if !empty.get() {
+                self.s.word(">")?
             }
         }
 
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 4c70816c0b8..a7913318789 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -133,22 +133,12 @@ impl_stable_hash_for!(struct hir::PathSegment {
     parameters
 });
 
-impl_stable_hash_for!(enum hir::PathParameters {
-    AngleBracketedParameters(data),
-    ParenthesizedParameters(data)
-});
-
-impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
+impl_stable_hash_for!(struct hir::PathParameters {
     lifetimes,
     types,
     infer_types,
-    bindings
-});
-
-impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
-    span,
-    inputs,
-    output
+    bindings,
+    parenthesized
 });
 
 impl_stable_hash_for!(enum hir::TyParamBound {
@@ -741,6 +731,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
             id,
+            hir_id: _,
             name,
             ref attrs,
             ref node,
@@ -774,6 +765,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
             id,
+            hir_id: _,
             name,
             ref vis,
             defaultness,
@@ -930,6 +922,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I
             name,
             ref attrs,
             id,
+            hir_id: _,
             ref node,
             ref vis,
             span
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 45b2a4a1e96..5f51579945e 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -663,6 +663,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::In
                 def_id.hash_stable(hcx, hasher);
                 t.hash_stable(hcx, hasher);
             }
+            ty::InstanceDef::CloneShim(def_id, t) => {
+                def_id.hash_stable(hcx, hasher);
+                t.hash_stable(hcx, hasher);
+            }
         }
     }
 }
diff --git a/src/librustc/infer/error_reporting/anon_anon_conflict.rs b/src/librustc/infer/error_reporting/anon_anon_conflict.rs
index 2e910968818..c80ce3c96f1 100644
--- a/src/librustc/infer/error_reporting/anon_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/anon_anon_conflict.rs
@@ -27,65 +27,84 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     //    { x.push(y); }.
     // The example gives
     // fn foo(x: &mut Vec<&u8>, y: &u8) {
-    //                    ---      --- these references must have the same lifetime
+    //                    ---      --- these references are declared with different lifetimes...
     //            x.push(y);
-    //            ^ data from `y` flows into `x` here
-    // It will later be extended to trait objects and structs.
+    //            ^ ...but data from `y` flows into `x` here
+    // It has been extended for the case of structs too.
+    // Consider the example
+    // struct Ref<'a> { x: &'a u32 }
+    // fn foo(mut x: Vec<Ref>, y: Ref) {
+    //                   ---      --- these structs are declared with different lifetimes...
+    //               x.push(y);
+    //               ^ ...but data from `y` flows into `x` here
+    // }
+    // It will later be extended to trait objects.
     pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
-
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
             _ => return false, // inapplicable
         };
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
-        let (ty1, ty2) = if self.is_suitable_anonymous_region(sup).is_some() &&
-                            self.is_suitable_anonymous_region(sub).is_some() {
-            if let (Some(anon_reg1), Some(anon_reg2)) =
-                (self.is_suitable_anonymous_region(sup), self.is_suitable_anonymous_region(sub)) {
-                let ((_, br1), (_, br2)) = (anon_reg1, anon_reg2);
-                if self.find_anon_type(sup, &br1).is_some() &&
-                   self.find_anon_type(sub, &br2).is_some() {
-                    (self.find_anon_type(sup, &br1).unwrap(),
-                     self.find_anon_type(sub, &br2).unwrap())
-                } else {
-                    return false;
-                }
-            } else {
-                return false;
-            }
-        } else {
-            return false; // inapplicable
-        };
+        let anon_reg_sup = or_false!(self.is_suitable_anonymous_region(sup));
 
-        if let (Some(sup_arg), Some(sub_arg)) =
+        let anon_reg_sub = or_false!(self.is_suitable_anonymous_region(sub));
+        let scope_def_id_sup = anon_reg_sup.def_id;
+        let bregion_sup = anon_reg_sup.boundregion;
+        let scope_def_id_sub = anon_reg_sub.def_id;
+        let bregion_sub = anon_reg_sub.boundregion;
+
+        let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup));
+
+        let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub));
+
+        let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
             (self.find_arg_with_anonymous_region(sup, sup),
              self.find_arg_with_anonymous_region(sub, sub)) {
-            let ((anon_arg1, _, _, _), (anon_arg2, _, _, _)) = (sup_arg, sub_arg);
 
-            let span_label_var1 = if let Some(simple_name) = anon_arg1.pat.simple_name() {
-                format!(" from `{}` ", simple_name)
-            } else {
-                format!(" ")
-            };
+            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 span_label_var2 = if let Some(simple_name) = anon_arg2.pat.simple_name() {
-                format!(" into `{}` ", simple_name)
+            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;
+            }
+
+            if anon_arg_sup == anon_arg_sub {
+                (format!("this type was declared with multiple lifetimes..."),
+                 format!(" with one lifetime"),
+                 format!(" into the other"))
             } else {
-                format!(" ")
-            };
-
-            struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
-                .span_label(ty1.span,
-                            format!("these references are not declared with the same lifetime..."))
-                .span_label(ty2.span, format!(""))
-                .span_label(span,
-                            format!("...but data{}flows{}here", span_label_var1, span_label_var2))
-                .emit();
+                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_label =
+                    format!("these two types are declared with different lifetimes...",);
+
+                (span_label, span_label_var1, span_label_var2)
+            }
         } else {
             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))
+            .emit();
         return true;
     }
 
@@ -94,7 +113,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// contains the anonymous type.
     ///
     /// # Arguments
-    ///
     /// region - the anonymous region corresponding to the anon_anon conflict
     /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
     ///
@@ -105,39 +123,56 @@ 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`.
-    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> {
         if let Some(anon_reg) = self.is_suitable_anonymous_region(region) {
-            let (def_id, _) = anon_reg;
+            let def_id = anon_reg.def_id;
             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                 let ret_ty = self.tcx.type_of(def_id);
                 if let ty::TyFnDef(_, _) = ret_ty.sty {
-                    if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
-                        if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
-                            return fndecl
-                                       .inputs
-                                       .iter()
-                                       .filter_map(|arg| {
-                                let mut nested_visitor = FindNestedTypeVisitor {
-                                    infcx: &self,
-                                    hir_map: &self.tcx.hir,
-                                    bound_region: *br,
-                                    found_type: None,
-                                };
-                                nested_visitor.visit_ty(&**arg);
-                                if nested_visitor.found_type.is_some() {
-                                    nested_visitor.found_type
-                                } else {
-                                    None
-                                }
-                            })
-                                       .next();
-                        }
-                    }
+                    let inputs: &[_] =
+                        match self.tcx.hir.get(node_id) {
+                            hir_map::NodeItem(&hir::Item {
+                                                  node: hir::ItemFn(ref fndecl, ..), ..
+                                              }) => &fndecl.inputs,
+                            hir_map::NodeTraitItem(&hir::TraitItem {
+                                                   node: hir::TraitItemKind::Method(ref fndecl, ..),
+                                                   ..
+                                               }) => &fndecl.decl.inputs,
+                            hir_map::NodeImplItem(&hir::ImplItem {
+                                                  node: hir::ImplItemKind::Method(ref fndecl, ..),
+                                                  ..
+                                              }) => &fndecl.decl.inputs,
+
+                            _ => &[],
+                        };
+
+                    return inputs
+                               .iter()
+                               .filter_map(|arg| {
+                                               self.find_component_for_bound_region(&**arg, br)
+                                           })
+                               .next();
                 }
             }
         }
         None
     }
+
+    // This method creates a FindNestedTypeVisitor which returns the type corresponding
+    // to the anonymous region.
+    fn find_component_for_bound_region(&self,
+                                       arg: &'gcx hir::Ty,
+                                       br: &ty::BoundRegion)
+                                       -> Option<(&'gcx hir::Ty)> {
+        let mut nested_visitor = FindNestedTypeVisitor {
+            infcx: &self,
+            hir_map: &self.tcx.hir,
+            bound_region: *br,
+            found_type: None,
+        };
+        nested_visitor.visit_ty(arg);
+        nested_visitor.found_type
+    }
 }
 
 // The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
@@ -176,8 +211,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
             hir::TyRptr(ref lifetime, _) => {
                 match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
                     // the lifetime of the TyRptr
-                    Some(&rl::Region::LateBoundAnon(debuijn_index, anon_index)) => {
-                        if debuijn_index.depth == 1 && anon_index == br_index {
+                    Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+                        if debruijn_index.depth == 1 && anon_index == br_index {
                             self.found_type = Some(arg);
                             return; // we can stop visiting now
                         }
@@ -191,6 +226,20 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
                     }
                 }
             }
+            // Checks if it is of type `hir::TyPath` which corresponds to a struct.
+            hir::TyPath(_) => {
+                let subvisitor = &mut TyPathVisitor {
+                                          infcx: self.infcx,
+                                          found_it: false,
+                                          bound_region: self.bound_region,
+                                          hir_map: self.hir_map,
+                                      };
+                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
+                // this will visit only outermost type
+                if subvisitor.found_it {
+                    self.found_type = Some(arg);
+                }
+            }
             _ => {}
         }
         // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
@@ -198,3 +247,56 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
         intravisit::walk_ty(self, arg);
     }
 }
+
+// The visitor captures the corresponding `hir::Ty` of the anonymous region
+// in the case of structs ie. `hir::TyPath`.
+// This visitor would be invoked for each lifetime corresponding to a struct,
+// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
+// where that lifetime appears. This allows us to highlight the
+// specific part of the type in the error message.
+struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    hir_map: &'a hir::map::Map<'gcx>,
+    found_it: bool,
+    bound_region: ty::BoundRegion,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    }
+
+    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
+        let br_index = match self.bound_region {
+            ty::BrAnon(index) => index,
+            _ => return,
+        };
+
+        match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
+            // the lifetime of the TyPath!
+            Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+                if debruijn_index.depth == 1 && anon_index == br_index {
+                    self.found_it = true;
+                }
+            }
+            Some(&rl::Region::Static) |
+            Some(&rl::Region::EarlyBound(_, _)) |
+            Some(&rl::Region::LateBound(_, _)) |
+            Some(&rl::Region::Free(_, _)) |
+            None => {
+                debug!("no arg found");
+            }
+        }
+    }
+
+    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
+        // ignore nested types
+        //
+        // If you have a type like `Foo<'a, &Ty>` we
+        // are only interested in the immediate lifetimes ('a).
+        //
+        // Making `visit_ty` empty will ignore the `&Ty` embedded
+        // inside, it will get reached by the outer visitor.
+        debug!("`Ty` corresponding to a struct is {:?}", arg);
+    }
+}
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index b5390da7e85..edf9ca89b33 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -24,7 +24,7 @@
 //! a span, but also more information so that we can generate a meaningful
 //! error message.
 //!
-//! Having a catalogue of all the different reasons an error can arise is
+//! Having a catalog of all the different reasons an error can arise is
 //! also useful for other reasons, like cross-referencing FAQs etc, though
 //! we are not really taking advantage of this yet.
 //!
@@ -75,8 +75,10 @@ use errors::{DiagnosticBuilder, DiagnosticStyledString};
 mod note;
 
 mod need_type_info;
-mod util;
+
 mod named_anon_conflict;
+#[macro_use]
+mod util;
 mod anon_anon_conflict;
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -899,9 +901,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
                 format!(" for lifetime parameter {}in generic type", br_string(br))
             }
-            infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
+            infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => {
                 format!(" for lifetime parameter {}in trait containing associated type `{}`",
-                        br_string(br), type_name)
+                        br_string(br), self.tcx.associated_item(def_id).name)
             }
             infer::EarlyBoundRegion(_, name) => {
                 format!(" for lifetime parameter `{}`",
diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs
index 491079a1f92..0aae008396a 100644
--- a/src/librustc/infer/error_reporting/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs
@@ -11,7 +11,6 @@
 //! Error Reporting for Anonymous Region Lifetime Errors
 //! where one region is named and the other is anonymous.
 use infer::InferCtxt;
-use ty;
 use infer::region_inference::RegionResolutionError::*;
 use infer::region_inference::RegionResolutionError;
 
@@ -30,8 +29,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // where the anonymous region appears (there must always be one; we
         // 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.
-        let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) =
+        // with the named one.//scope_def_id
+        let (named, anon_arg_info, region_info) =
             if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() {
                 (sub,
                  self.find_arg_with_anonymous_region(sup, sub).unwrap(),
@@ -44,50 +43,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 return false; // inapplicable
             };
 
-        // Here, we check for the case where the anonymous region
-        // is in the return type.
-        // FIXME(#42703) - Need to handle certain cases here.
-        let ret_ty = self.tcx.type_of(scope_def_id);
-        match ret_ty.sty {
-            ty::TyFnDef(_, _) => {
-                let sig = ret_ty.fn_sig(self.tcx);
-                let late_bound_regions = self.tcx
-                    .collect_referenced_late_bound_regions(&sig.output());
-                if late_bound_regions.iter().any(|r| *r == br) {
-                    return false;
-                }
-            }
-            _ => {}
-        }
-
-        // Here we check for the case where anonymous region
-        // corresponds to self and if yes, we display E0312.
-        // FIXME(#42700) - Need to format self properly to
-        // enable E0621 for it.
-        if is_first &&
-           self.tcx
-               .opt_associated_item(scope_def_id)
-               .map(|i| i.method_has_self_argument)
-               .unwrap_or(false) {
+        let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
+                                                                       anon_arg_info.arg_ty,
+                                                                       anon_arg_info.bound_region,
+                                                                       anon_arg_info.is_first,
+                                                                       region_info.def_id,
+                                                                       region_info.is_impl_item);
+        if is_impl_item {
             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))
+        if self.is_return_type_anon(scope_def_id, br) || self.is_self_anon(is_first, scope_def_id) {
+            return false;
         } else {
-            ("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();
+            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())
+            };
+
+            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 c8f78367420..04153038da8 100644
--- a/src/librustc/infer/error_reporting/util.rs
+++ b/src/librustc/infer/error_reporting/util.rs
@@ -16,6 +16,40 @@ use ty::{self, Region};
 use hir::def_id::DefId;
 use hir::map as hir_map;
 
+macro_rules! or_false {
+     ($v:expr) => {
+          match $v {
+               Some(v) => v,
+               None => return false,
+          }
+     }
+}
+
+// The struct contains the information about the anonymous region
+// we are searching for.
+pub struct AnonymousArgInfo<'tcx> {
+    // the argument corresponding to the anonymous region
+    pub arg: &'tcx hir::Arg,
+    // the type corresponding to the anonymopus region argument
+    pub arg_ty: ty::Ty<'tcx>,
+    // the ty::BoundRegion corresponding to the anonymous region
+    pub bound_region: ty::BoundRegion,
+    // corresponds to id the argument is the first parameter
+    // in the declaration
+    pub is_first: bool,
+}
+
+// This struct contains information regarding the
+// Refree((FreeRegion) corresponding to lifetime conflict
+pub struct FreeRegionInfo {
+    // def id corresponding to FreeRegion
+    pub def_id: DefId,
+    // the bound region corresponding to FreeRegion
+    pub boundregion: ty::BoundRegion,
+    // checks if bound region is in Impl Item
+    pub is_impl_item: bool,
+}
+
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // This method walks the Type of the function body arguments using
     // `fold_regions()` function and returns the
@@ -28,14 +62,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // i32, which is the type of y but with the anonymous region replaced
     // with 'a, the corresponding bound region and is_first which is true if
     // the hir::Arg is the first argument in the function declaration.
-    pub fn find_arg_with_anonymous_region
-        (&self,
-         anon_region: Region<'tcx>,
-         replace_region: Region<'tcx>)
-         -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
+    pub fn find_arg_with_anonymous_region(&self,
+                                          anon_region: Region<'tcx>,
+                                          replace_region: Region<'tcx>)
+                                          -> Option<AnonymousArgInfo> {
 
         if let ty::ReFree(ref free_region) = *anon_region {
-
             let id = free_region.scope;
             let hir = &self.tcx.hir;
             if let Some(node_id) = hir.as_local_node_id(id) {
@@ -57,7 +89,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                     });
                                 if found_anon_region {
                                     let is_first = index == 0;
-                                    Some((arg, new_arg_ty, free_region.bound_region, is_first))
+                                    Some(AnonymousArgInfo {
+                                             arg: arg,
+                                             arg_ty: new_arg_ty,
+                                             bound_region: free_region.bound_region,
+                                             is_first: is_first,
+                                         })
                                 } else {
                                     None
                                 }
@@ -79,42 +116,81 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
     // This method returns whether the given Region is Anonymous
     // and returns the DefId and the BoundRegion corresponding to the given region.
-    pub fn is_suitable_anonymous_region(&self,
-                                        region: Region<'tcx>)
-                                        -> Option<(DefId, ty::BoundRegion)> {
+    pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
         if let ty::ReFree(ref free_region) = *region {
-            if let ty::BrAnon(..) = free_region.bound_region{
-                    let anonymous_region_binding_scope = free_region.scope;
-                    let node_id = self.tcx
-                        .hir
-                        .as_local_node_id(anonymous_region_binding_scope)
-                        .unwrap();
-                    match self.tcx.hir.find(node_id) {
-                        Some(hir_map::NodeItem(..)) |
-                        Some(hir_map::NodeTraitItem(..)) => {
-                            // Success -- proceed to return Some below
-                        }
-                        Some(hir_map::NodeImplItem(..)) => {
-                            let container_id = self.tcx
-                                .associated_item(anonymous_region_binding_scope)
-                                .container
-                                .id();
-                            if self.tcx.impl_trait_ref(container_id).is_some() {
-                                // For now, we do not try to target impls of traits. This is
-                                // because this message is going to suggest that the user
-                                // change the fn signature, but they may not be free to do so,
-                                // since the signature must match the trait.
-                                //
-                                // FIXME(#42706) -- in some cases, we could do better here.
-                                return None;
-                            }
-                        }
-                        _ => return None, // inapplicable
-                        // we target only top-level functions
+            if let ty::BrAnon(..) = free_region.bound_region {
+                let anonymous_region_binding_scope = free_region.scope;
+                let node_id = self.tcx
+                    .hir
+                    .as_local_node_id(anonymous_region_binding_scope)
+                    .unwrap();
+                let mut is_impl_item = false;
+                match self.tcx.hir.find(node_id) {
+
+                    Some(hir_map::NodeItem(..)) |
+                    Some(hir_map::NodeTraitItem(..)) => {
+                        // Success -- proceed to return Some below
                     }
-                    return Some((anonymous_region_binding_scope, free_region.bound_region));
+                    Some(hir_map::NodeImplItem(..)) => {
+                        is_impl_item =
+                            self.is_bound_region_in_impl_item(anonymous_region_binding_scope);
+                    }
+                    _ => return None,
                 }
+                return Some(FreeRegionInfo {
+                                def_id: anonymous_region_binding_scope,
+                                boundregion: free_region.bound_region,
+                                is_impl_item: is_impl_item,
+                            });
             }
-            None
         }
+        None
+    }
+
+    // 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 {
+        let ret_ty = self.tcx.type_of(scope_def_id);
+        match ret_ty.sty {
+            ty::TyFnDef(_, _) => {
+                let sig = ret_ty.fn_sig(self.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;
+                }
+            }
+            _ => {}
+        }
+        false
+    }
+    // Here we check for the case where anonymous region
+    // corresponds to self and if yes, we display E0312.
+    // FIXME(#42700) - Need to format self properly to
+    // enable E0621 for it.
+    pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
+        is_first &&
+        self.tcx
+            .opt_associated_item(scope_def_id)
+            .map(|i| i.method_has_self_argument) == Some(true)
+    }
+
+    // Here we check if the bound region is in Impl Item.
+    pub fn is_bound_region_in_impl_item(&self, anonymous_region_binding_scope: DefId) -> bool {
+        let container_id = self.tcx
+            .associated_item(anonymous_region_binding_scope)
+            .container
+            .id();
+        if self.tcx.impl_trait_ref(container_id).is_some() {
+            // For now, we do not try to target impls of traits. This is
+            // because this message is going to suggest that the user
+            // change the fn signature, but they may not be free to do so,
+            // since the signature must match the trait.
+            //
+            // FIXME(#42706) -- in some cases, we could do better here.
+            return true;
+        }
+        false
+    }
 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 186eab724db..6c9b9d853f4 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -274,7 +274,7 @@ pub enum LateBoundRegionConversionTime {
     HigherRankedType,
 
     /// when projecting an associated type
-    AssocTypeProjection(ast::Name), // FIXME(tschottdorf): should contain DefId, not Name
+    AssocTypeProjection(DefId),
 }
 
 /// Reasons to create a region inference variable
diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs
index 6a1f8f1d069..639a330dc6e 100644
--- a/src/librustc/infer/resolve.rs
+++ b/src/librustc/infer/resolve.rs
@@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'g
 }
 
 /// The opportunistic type and region resolver is similar to the
-/// opportunistic type resolver, but also opportunistly resolves
+/// opportunistic type resolver, but also opportunistically resolves
 /// regions. It is useful for canonicalization.
 pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 5b0760e561e..152b2e2aa5e 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -29,7 +26,7 @@
 #![feature(core_intrinsics)]
 #![feature(discriminant_value)]
 #![feature(i128_type)]
-#![feature(libc)]
+#![cfg_attr(windows, feature(libc))]
 #![feature(never_type)]
 #![feature(nonzero)]
 #![feature(quote)]
@@ -48,6 +45,7 @@ extern crate core;
 extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
+#[cfg(windows)]
 extern crate libc;
 extern crate owning_ref;
 extern crate rustc_back;
@@ -65,7 +63,9 @@ extern crate serialize as rustc_serialize; // used by deriving
 
 // Note that librustc doesn't actually depend on these crates, see the note in
 // `Cargo.toml` for this crate about why these are here.
+#[allow(unused_extern_crates)]
 extern crate flate2;
+#[allow(unused_extern_crates)]
 extern crate test;
 
 #[macro_use]
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index cbe642a9a76..811bf977610 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,
-    Allow,
+    Warn,
     "extern crates that are never used"
 }
 
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 40d78d0138b..4d1374b69b8 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -101,7 +101,7 @@ pub struct FutureIncompatibleInfo {
     pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code
 }
 
-/// The targed of the `by_name` map, which accounts for renaming/deprecation.
+/// The target of the `by_name` map, which accounts for renaming/deprecation.
 enum TargetLint {
     /// A direct lint target
     Id(LintId),
@@ -121,10 +121,10 @@ pub enum FindLintError {
 
 pub enum CheckLintNameResult<'a> {
     Ok(&'a [LintId]),
-    // Lint doesn't exist
+    /// Lint doesn't exist
     NoLint,
-    // The lint is either renamed or removed. This is the warning
-    // message.
+    /// The lint is either renamed or removed. This is the warning
+    /// message.
     Warning(String),
 }
 
@@ -253,7 +253,7 @@ impl LintStore {
         }
     }
 
-    // Checks the validity of lint names derived from the command line
+    /// Checks the validity of lint names derived from the command line
     pub fn check_lint_name_cmdline(&self,
                                    sess: &Session,
                                    lint_name: &str,
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs
index ab9d4f75597..ab086e5b8e9 100644
--- a/src/librustc/lint/levels.rs
+++ b/src/librustc/lint/levels.rs
@@ -83,10 +83,13 @@ impl LintLevelSets {
         });
     }
 
-    fn get_lint_level(&self, lint: &'static Lint, idx: u32)
+    fn get_lint_level(&self,
+                      lint: &'static Lint,
+                      idx: u32,
+                      aux: Option<&FxHashMap<LintId, (Level, LintSource)>>)
         -> (Level, LintSource)
     {
-        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx);
+        let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
         // lint.
@@ -97,7 +100,9 @@ impl LintLevelSets {
         // `allow(warnings)` in scope then we want to respect that instead.
         if level == Level::Warn {
             let (warnings_level, warnings_src) =
-                self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx);
+                self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS),
+                                       idx,
+                                       aux);
             if let Some(configured_warning_level) = warnings_level {
                 if configured_warning_level != Level::Warn {
                     level = configured_warning_level;
@@ -112,9 +117,17 @@ impl LintLevelSets {
         return (level, src)
     }
 
-    fn get_lint_id_level(&self, id: LintId, mut idx: u32)
+    fn get_lint_id_level(&self,
+                         id: LintId,
+                         mut idx: u32,
+                         aux: Option<&FxHashMap<LintId, (Level, LintSource)>>)
         -> (Option<Level>, LintSource)
     {
+        if let Some(specs) = aux {
+            if let Some(&(level, src)) = specs.get(&id) {
+                return (Some(level), src)
+            }
+        }
         loop {
             match self.list[idx as usize] {
                 LintSet::CommandLine { ref specs } => {
@@ -212,21 +225,35 @@ impl<'a> LintLevelsBuilder<'a> {
                             specs.insert(*id, (level, src));
                         }
                     }
+
+                    _ if !self.warn_about_weird_lints => {}
+
                     CheckLintNameResult::Warning(ref msg) => {
-                        if self.warn_about_weird_lints {
-                            self.struct_lint(builtin::RENAMED_AND_REMOVED_LINTS,
-                                             Some(li.span.into()),
-                                             msg)
-                                .emit();
-                        }
+                        let lint = builtin::RENAMED_AND_REMOVED_LINTS;
+                        let (level, src) = self.sets.get_lint_level(lint,
+                                                                    self.cur,
+                                                                    Some(&specs));
+                        lint::struct_lint_level(self.sess,
+                                                lint,
+                                                level,
+                                                src,
+                                                Some(li.span.into()),
+                                                msg)
+                            .emit();
                     }
                     CheckLintNameResult::NoLint => {
-                        if self.warn_about_weird_lints {
-                            self.struct_lint(builtin::UNKNOWN_LINTS,
-                                             Some(li.span.into()),
-                                             &format!("unknown lint: `{}`", name))
-                                .emit();
-                        }
+                        let lint = builtin::UNKNOWN_LINTS;
+                        let (level, src) = self.sets.get_lint_level(lint,
+                                                                    self.cur,
+                                                                    Some(&specs));
+                        let msg = format!("unknown lint: `{}`", name);
+                        lint::struct_lint_level(self.sess,
+                                                lint,
+                                                level,
+                                                src,
+                                                Some(li.span.into()),
+                                                &msg)
+                            .emit();
                     }
                 }
             }
@@ -236,7 +263,7 @@ impl<'a> LintLevelsBuilder<'a> {
             if level == Level::Forbid {
                 continue
             }
-            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur) {
+            let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) {
                 (Some(Level::Forbid), src) => src,
                 _ => continue,
             };
@@ -298,7 +325,7 @@ impl<'a> LintLevelsBuilder<'a> {
                        msg: &str)
         -> DiagnosticBuilder<'a>
     {
-        let (level, src) = self.sets.get_lint_level(lint, self.cur);
+        let (level, src) = self.sets.get_lint_level(lint, self.cur, None);
         lint::struct_lint_level(self.sess, lint, level, src, span, msg)
     }
 
@@ -337,7 +364,7 @@ impl LintLevelMap {
         -> Option<(Level, LintSource)>
     {
         self.id_to_set.get(&id).map(|idx| {
-            self.sets.get_lint_level(lint, *idx)
+            self.sets.get_lint_level(lint, *idx, None)
         })
     }
 }
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 8a2b115e58d..b8624722692 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -630,8 +630,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let krate = tcx.hir.krate();
     let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor {
-        tcx: tcx,
-        live_symbols: live_symbols,
+        tcx,
+        live_symbols,
     };
     intravisit::walk_crate(&mut visitor, krate);
 }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 01ed79096b1..9ba4252b52e 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -274,6 +274,7 @@ language_item_table! {
     SizedTraitLangItem,              "sized",                   sized_trait;
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
     CopyTraitLangItem,               "copy",                    copy_trait;
+    CloneTraitLangItem,              "clone",                   clone_trait;
     SyncTraitLangItem,               "sync",                    sync_trait;
     FreezeTraitLangItem,             "freeze",                  freeze_trait;
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 070ad515908..8e5f748c78e 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1482,12 +1482,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 };
 
                 if is_assigned {
-                    self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp,
+                    self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
                         &format!("variable `{}` is assigned to, but never used",
+                                 name),
+                        &format!("to disable this warning, consider using `_{}` instead",
                                  name));
                 } else if name != "self" {
-                    self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp,
-                        &format!("unused variable: `{}`", name));
+                    self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
+                        &format!("unused variable: `{}`", name),
+                        &format!("to disable this warning, consider using `_{}` instead",
+                                 name));
                 }
             }
             true
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 8919d0afc1d..8cd023b8e63 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -332,7 +332,7 @@ impl MutabilityCategory {
 
     fn from_local(tcx: TyCtxt, tables: &ty::TypeckTables, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.hir.get(id) {
-            hir_map::NodeLocal(p) => match p.node {
+            hir_map::NodeBinding(p) => match p.node {
                 PatKind::Binding(..) => {
                     let bm = *tables.pat_binding_modes()
                                     .get(p.hir_id)
@@ -873,10 +873,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned()
                                    .unwrap_or(false);
 
-        // When the corresponding feature isn't toggled, only promote `[T; 0]`.
+        // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
             ty::TyArray(_, 0) => true,
-            _ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion,
+            _ => promotable,
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 9133a5e777d..45a3080ed91 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -72,7 +72,7 @@ use mir::transform::MirSource;
 ///  (M1.): Misc extent of the whole `let a = ...;` statement.
 ///  (M2.): Misc extent of the `f()` expression.
 ///  (M3.): Misc extent of the `f().g(..)` expression.
-///  (M4.): Misc extent of the block labelled `'b:`.
+///  (M4.): Misc extent of the block labeled `'b:`.
 ///  (M5.): Misc extent of the `let x = d();` statement
 ///  (D6.): DestructionScope for temporaries created during M5.
 ///  (R7.): Remainder extent for block `'b:`, stmt 0 (let x = ...).
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 13efa94a5c9..a8e98e53db3 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -915,18 +915,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                                 def: Def,
                                 depth: usize,
                                 params: &'tcx hir::PathParameters) {
-        let data = match *params {
-            hir::ParenthesizedParameters(ref data) => {
-                self.visit_fn_like_elision(&data.inputs, data.output.as_ref());
-                return;
-            }
-            hir::AngleBracketedParameters(ref data) => data
-        };
+        if params.parenthesized {
+            self.visit_fn_like_elision(params.inputs(), Some(&params.bindings[0].ty));
+            return;
+        }
 
-        if data.lifetimes.iter().all(|l| l.is_elided()) {
-            self.resolve_elided_lifetimes(&data.lifetimes);
+        if params.lifetimes.iter().all(|l| l.is_elided()) {
+            self.resolve_elided_lifetimes(&params.lifetimes);
         } else {
-            for l in &data.lifetimes { self.visit_lifetime(l); }
+            for l in &params.lifetimes { self.visit_lifetime(l); }
         }
 
         // Figure out if this is a type/trait segment,
@@ -995,13 +992,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                             Some(Region::Static)
                         }
                     }
-                    Set1::One(r) => r.subst(&data.lifetimes, map),
+                    Set1::One(r) => r.subst(&params.lifetimes, map),
                     Set1::Many => None
                 }
             }).collect()
         });
 
-        for (i, ty) in data.types.iter().enumerate() {
+        for (i, ty) in params.types.iter().enumerate() {
             if let Some(&lt) = object_lifetime_defaults.get(i) {
                 let scope = Scope::ObjectLifetimeDefault {
                     lifetime: lt,
@@ -1013,7 +1010,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             }
         }
 
-        for b in &data.bindings { self.visit_assoc_type_binding(b); }
+        for b in &params.bindings { self.visit_assoc_type_binding(b); }
     }
 
     fn visit_fn_like_elision(&mut self, inputs: &'tcx [P<hir::Ty>],
@@ -1081,20 +1078,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 Some(body)
             }
 
-            // `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
-            hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None,
-
-            // Foreign `fn` decls are terrible because we messed up,
-            // and their return types get argument type elision.
-            // And now too much code out there is abusing this rule.
-            hir::map::NodeForeignItem(_) => {
-                let arg_scope = Scope::Elision {
-                    elide: arg_elide,
-                    s: self.scope
-                };
-                self.with(arg_scope, |_, this| this.visit_ty(output));
-                return;
-            }
+            // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds).
+            hir::map::NodeForeignItem(_) | hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None,
 
             // Everything else (only closures?) doesn't
             // actually enjoy elision in return types.
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 5158c7e94af..d2ed29a3a0f 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -123,7 +123,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                    item_sp: Span, kind: AnnotationKind, visit_children: F)
         where F: FnOnce(&mut Self)
     {
-        if self.index.staged_api[&LOCAL_CRATE] {
+        if self.tcx.sess.features.borrow().staged_api {
+            // This crate explicitly wants staged API.
             debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
             if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
                 self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \
@@ -204,6 +205,15 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                 }
             }
 
+            // Propagate unstability.  This can happen even for non-staged-api crates in case
+            // -Zforce-unstable-if-unmarked is set.
+            if let Some(stab) = self.parent_stab {
+                if stab.level.is_unstable() {
+                    let def_id = self.tcx.hir.local_def_id(id);
+                    self.index.stab_map.insert(def_id, Some(stab));
+                }
+            }
+
             if let Some(depr) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
                 if kind == AnnotationKind::Prohibited {
                     self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs
index 5aab46b3cef..74c3408c4c2 100644
--- a/src/librustc/mir/traversal.rs
+++ b/src/librustc/mir/traversal.rs
@@ -216,7 +216,7 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
 ///
 /// Reverse postorder is the reverse order of a postorder traversal.
 /// This is different to a preorder traversal and represents a natural
-/// linearisation of control-flow.
+/// linearization of control-flow.
 ///
 /// ```text
 ///
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 6995f099677..99fe8e60ae5 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -918,6 +918,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
     identify_regions: bool = (false, parse_bool, [UNTRACKED],
         "make unnamed regions display as '# (where # is some non-ident unique id)"),
+    borrowck_mir: bool = (false, parse_bool, [UNTRACKED],
+        "implicitly treat functions as if they have `#[rustc_mir_borrowck]` attribute"),
     time_passes: bool = (false, parse_bool, [UNTRACKED],
         "measure time of each rustc pass"),
     count_llvm_insns: bool = (false, parse_bool,
@@ -993,6 +995,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
           "enable queries of the dependency graph for regression testing"),
+    profile_queries: bool = (false, parse_bool, [UNTRACKED],
+          "trace and profile the queries of the incremental compilation framework"),
+    profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
+          "trace and profile the queries and keys of the incremental compilation framework"),
     no_analysis: bool = (false, parse_bool, [UNTRACKED],
           "parse and expand the source, but run no analysis"),
     extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 3aea0722d0e..823a637c7e0 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -389,6 +389,13 @@ impl Session {
     }
     pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
     pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
+    pub fn profile_queries(&self) -> bool {
+        self.opts.debugging_opts.profile_queries ||
+            self.opts.debugging_opts.profile_queries_and_keys
+    }
+    pub fn profile_queries_and_keys(&self) -> bool {
+        self.opts.debugging_opts.profile_queries_and_keys
+    }
     pub fn count_llvm_insns(&self) -> bool {
         self.opts.debugging_opts.count_llvm_insns
     }
@@ -429,6 +436,31 @@ impl Session {
             .unwrap_or(self.opts.debug_assertions)
     }
 
+    pub fn crt_static(&self) -> bool {
+        // If the target does not opt in to crt-static support, use its default.
+        if self.target.target.options.crt_static_respected {
+            self.crt_static_feature()
+        } else {
+            self.target.target.options.crt_static_default
+        }
+    }
+
+    pub fn crt_static_feature(&self) -> bool {
+        let requested_features = self.opts.cg.target_feature.split(',');
+        let found_negative = requested_features.clone().any(|r| r == "-crt-static");
+        let found_positive = requested_features.clone().any(|r| r == "+crt-static");
+
+        // If the target we're compiling for requests a static crt by default,
+        // then see if the `-crt-static` feature was passed to disable that.
+        // Otherwise if we don't have a static crt by default then see if the
+        // `+crt-static` feature was passed.
+        if self.target.target.options.crt_static_default {
+            !found_negative
+        } else {
+            found_positive
+        }
+    }
+
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
         !self.target.target.options.eliminate_frame_pointer
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c04d448716c..3e64c8c7dea 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1111,8 +1111,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             ObligationCauseCode::StructInitializerSized => {
                 err.note("structs must have a statically known size to be initialized");
             }
-            ObligationCauseCode::FieldSized => {
-                err.note("only the last field of a struct may have a dynamically sized type");
+            ObligationCauseCode::FieldSized(ref item) => {
+                match *item {
+                    AdtKind::Struct => {
+                        err.note("only the last field of a struct may have a dynamically \
+                                  sized type");
+                    }
+                    AdtKind::Union => {
+                        err.note("no field of a union may have a dynamically sized type");
+                    }
+                    AdtKind::Enum => {
+                        err.note("no field of an enum variant may have a dynamically sized type");
+                    }
+                }
             }
             ObligationCauseCode::ConstSized => {
                 err.note("constant expressions must have a statically known size");
@@ -1154,8 +1165,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
         let current_limit = self.tcx.sess.recursion_limit.get();
         let suggested_limit = current_limit * 2;
-        err.help(&format!(
-                          "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+        err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                           suggested_limit));
     }
 }
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 4f1eb616920..78e47693caa 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -37,7 +37,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
 /// consists of a list of obligations that must be (eventually)
 /// satisfied. The job is to track which are satisfied, which yielded
 /// errors, and which are still pending. At any point, users can call
-/// `select_where_possible`, and the fulfilment context will try to do
+/// `select_where_possible`, and the fulfillment context will try to do
 /// selection, retaining only those obligations that remain
 /// ambiguous. This may be helpful in pushing type inference
 /// along. Once all type inference constraints have been generated, the
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index d1938197e65..5bae82c1a33 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -20,7 +20,7 @@ use hir::def_id::DefId;
 use middle::region::RegionMaps;
 use middle::free_region::FreeRegionMap;
 use ty::subst::Substs;
-use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate};
+use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate};
 use ty::error::{ExpectedFound, TypeError};
 use infer::{InferCtxt};
 
@@ -133,7 +133,7 @@ pub enum ObligationCauseCode<'tcx> {
     RepeatVec,
 
     /// Types of fields (other than the last) in a struct must be sized.
-    FieldSized,
+    FieldSized(AdtKind),
 
     /// Constant expressions must be sized.
     ConstSized,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 3e39d592135..46bdb1344b2 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1296,6 +1296,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
          } else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
              self.assemble_candidates_for_unsizing(obligation, &mut candidates);
          } else {
+            if self.tcx().lang_items.clone_trait() == Some(def_id) {
+                // Same builtin conditions as `Copy`, i.e. every type which has builtin support
+                // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
+                // types have builtin support for `Clone`.
+                let clone_conditions = self.copy_conditions(obligation);
+                self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
+            }
+
              self.assemble_closure_candidates(obligation, &mut candidates)?;
              self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
              self.assemble_candidates_from_impls(obligation, &mut candidates)?;
@@ -2164,8 +2172,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         match candidate {
             BuiltinCandidate { has_nested } => {
-                Ok(VtableBuiltin(
-                    self.confirm_builtin_candidate(obligation, has_nested)))
+                let data = self.confirm_builtin_candidate(obligation, has_nested);
+                Ok(VtableBuiltin(data))
             }
 
             ParamCandidate(param) => {
@@ -2271,6 +2279,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 _ if Some(trait_def) == self.tcx().lang_items.copy_trait() => {
                     self.copy_conditions(obligation)
                 }
+                _ if Some(trait_def) == self.tcx().lang_items.clone_trait() => {
+                    self.copy_conditions(obligation)
+                }
                 _ => bug!("unexpected builtin trait {:?}", trait_def)
             };
             let nested = match conditions {
@@ -2291,6 +2302,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         debug!("confirm_builtin_candidate: obligations={:?}",
                obligations);
+
         VtableBuiltinData { nested: obligations }
     }
 
@@ -2598,8 +2610,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
     fn confirm_builtin_unsize_candidate(&mut self,
                                         obligation: &TraitObligation<'tcx>,)
-                                        -> Result<VtableBuiltinData<PredicateObligation<'tcx>>,
-                                                  SelectionError<'tcx>> {
+        -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>>
+    {
         let tcx = self.tcx();
 
         // assemble_candidates_for_unsizing should ensure there are no late bound
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index f1c176561ea..d913c76ec3c 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -195,7 +195,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
             super::ReturnType(id) => Some(super::ReturnType(id)),
             super::SizedReturnType => Some(super::SizedReturnType),
             super::RepeatVec => Some(super::RepeatVec),
-            super::FieldSized => Some(super::FieldSized),
+            super::FieldSized(item) => Some(super::FieldSized(item)),
             super::ConstSized => Some(super::ConstSized),
             super::SharedStatic => Some(super::SharedStatic),
             super::BuiltinDerivedObligation(ref cause) => {
@@ -300,7 +300,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
                 })
             }
             traits::VtableParam(n) => Some(traits::VtableParam(n)),
-            traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)),
+            traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
             traits::VtableObject(traits::VtableObjectData {
                 upcast_trait_ref,
                 vtable_base,
@@ -484,7 +484,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
@@ -532,7 +532,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
-            super::FieldSized |
+            super::FieldSized(_) |
             super::ConstSized |
             super::SharedStatic |
             super::BlockTailExpression(_) |
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index f71ad67bd1d..6ce2232eb3e 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -797,6 +797,8 @@ pub struct GlobalCtxt<'tcx> {
 
     pub maybe_unused_trait_imports: NodeSet,
 
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
+
     // Internal cache for metadata decoding. No need to track deps on this.
     pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
 
@@ -851,7 +853,7 @@ pub struct GlobalCtxt<'tcx> {
 
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
-    /// error reporting, and so is lazily initialised and generally
+    /// error reporting, and so is lazily initialized and generally
     /// shouldn't taint the common path (hence the RefCell).
     pub all_traits: RefCell<Option<Vec<DefId>>>,
 }
@@ -1038,6 +1040,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             mir_passes,
             freevars: RefCell::new(resolutions.freevars),
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
+            maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
             rcache: RefCell::new(FxHashMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
@@ -1695,8 +1698,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                          substs: &'tcx Substs<'tcx>)
         -> Ty<'tcx> {
             self.mk_ty(TyProjection(ProjectionTy {
-                item_def_id: item_def_id,
-                substs: substs,
+                item_def_id,
+                substs,
             }))
         }
 
@@ -1840,6 +1843,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.struct_span_lint_node(lint, id, span.into(), msg).emit()
     }
 
+    pub fn lint_node_note<S: Into<MultiSpan>>(self,
+                                              lint: &'static Lint,
+                                              id: NodeId,
+                                              span: S,
+                                              msg: &str,
+                                              note: &str) {
+        let mut err = self.struct_span_lint_node(lint, id, span.into(), msg);
+        err.note(note);
+        err.emit()
+    }
+
     pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
         -> (lint::Level, lint::LintSource)
     {
diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs
index 896682e2370..3629709e6a4 100644
--- a/src/librustc/ty/inhabitedness/def_id_forest.rs
+++ b/src/librustc/ty/inhabitedness/def_id_forest.rs
@@ -26,7 +26,7 @@ pub struct DefIdForest {
     /// The minimal set of DefIds required to represent the whole set.
     /// If A and B are DefIds in the DefIdForest, and A is a descendant
     /// of B, then only B will be in root_ids.
-    /// We use a SmallVec here because (for its use for cacheing inhabitedness)
+    /// We use a SmallVec here because (for its use for caching inhabitedness)
     /// its rare that this will contain even two ids.
     root_ids: SmallVec<[DefId; 1]>,
 }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 32063a2dda6..7d543f689c2 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -24,15 +24,22 @@ pub struct Instance<'tcx> {
 pub enum InstanceDef<'tcx> {
     Item(DefId),
     Intrinsic(DefId),
-    // <fn() as FnTrait>::call_*
-    // def-id is FnTrait::call_*
+
+    /// <fn() as FnTrait>::call_*
+    /// def-id is FnTrait::call_*
     FnPtrShim(DefId, Ty<'tcx>),
-    // <Trait as Trait>::fn
+
+    /// <Trait as Trait>::fn
     Virtual(DefId, usize),
-    // <[mut closure] as FnOnce>::call_once
+
+    /// <[mut closure] as FnOnce>::call_once
     ClosureOnceShim { call_once: DefId },
-    // drop_in_place::<T>; None for empty drop glue.
+
+    /// drop_in_place::<T>; None for empty drop glue.
     DropGlue(DefId, Option<Ty<'tcx>>),
+
+    /// Builtin method implementation, e.g. `Clone::clone`.
+    CloneShim(DefId, Ty<'tcx>),
 }
 
 impl<'tcx> InstanceDef<'tcx> {
@@ -43,9 +50,9 @@ impl<'tcx> InstanceDef<'tcx> {
             InstanceDef::FnPtrShim(def_id, _) |
             InstanceDef::Virtual(def_id, _) |
             InstanceDef::Intrinsic(def_id, ) |
-            InstanceDef::ClosureOnceShim { call_once: def_id }
-                => def_id,
-            InstanceDef::DropGlue(def_id, _) => def_id
+            InstanceDef::ClosureOnceShim { call_once: def_id } |
+            InstanceDef::DropGlue(def_id, _) |
+            InstanceDef::CloneShim(def_id, _) => def_id
         }
     }
 
@@ -80,6 +87,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> {
             InstanceDef::DropGlue(_, ty) => {
                 write!(f, " - shim({:?})", ty)
             }
+            InstanceDef::CloneShim(_, ty) => {
+                write!(f, " - shim({:?})", ty)
+            }
         }
     }
 }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 76a20ed8f30..5caf5139812 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -13,7 +13,6 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use ty::{self, Ty, TyCtxt};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
 
 use std::cell::Cell;
 
@@ -222,11 +221,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
-            !force_no_types && {
-                // Otherwise, use types if we can query them without inducing a cycle.
-                ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
-                    ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
-            }
+            !force_no_types
         });
 
         if !use_types {
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index a640da31eec..a73202ced61 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
+use errors::{Diagnostic, DiagnosticBuilder};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::def::Def;
 use hir;
@@ -28,10 +29,11 @@ use ty::steal::Steal;
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
 use util::nodemap::{DefIdSet, NodeSet};
+use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
-use std::cell::{RefCell, RefMut};
+use std::cell::{RefCell, RefMut, Cell};
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -187,7 +189,18 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
 
 struct QueryMap<D: QueryDescription> {
     phantom: PhantomData<D>,
-    map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>,
+    map: FxHashMap<D::Key, QueryValue<D::Value>>,
+}
+
+struct QueryValue<T> {
+    value: T,
+    index: DepNodeIndex,
+    diagnostics: Option<Box<QueryDiagnostics>>,
+}
+
+struct QueryDiagnostics {
+    diagnostics: Vec<Diagnostic>,
+    emitted_diagnostics: Cell<bool>,
 }
 
 impl<M: QueryDescription> QueryMap<M> {
@@ -199,13 +212,15 @@ impl<M: QueryDescription> QueryMap<M> {
     }
 }
 
-pub struct CycleError<'a, 'tcx: 'a> {
+struct CycleError<'a, 'tcx: 'a> {
     span: Span,
     cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
+    fn report_cycle(self, CycleError { span, cycle }: CycleError)
+        -> DiagnosticBuilder<'a>
+    {
         // Subtle: release the refcell lock before invoking `describe()`
         // below by dropping `cycle`.
         let stack = cycle.to_vec();
@@ -234,8 +249,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             err.note(&format!("...which then again requires {}, completing the cycle.",
                               stack[0].1.describe(self)));
 
-            err.emit();
-        });
+            return err
+        })
     }
 
     fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
@@ -501,6 +516,18 @@ impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        "checking if the crate is_compiler_builtins".to_string()
+    }
+}
+
+impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        "checking if the crate has_global_allocator".to_string()
+    }
+}
+
 impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
     fn describe(_: TyCtxt, _: DefId) -> String {
         "getting crate's ExternCrateData".to_string()
@@ -513,6 +540,29 @@ impl<'tcx> QueryDescription for queries::lint_levels<'tcx> {
     }
 }
 
+// If enabled, send a message to the profile-queries thread
+macro_rules! profq_msg {
+    ($tcx:expr, $msg:expr) => {
+        if cfg!(debug_assertions) {
+            if  $tcx.sess.profile_queries() {
+                profq_msg($msg)
+            }
+        }
+    }
+}
+
+// If enabled, format a key using its debug string, which can be
+// expensive to compute (in terms of time).
+macro_rules! profq_key {
+    ($tcx:expr, $key:expr) => {
+        if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries_and_keys() {
+                Some(format!("{:?}", $key))
+            } else { None }
+        } else { None }
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -539,6 +589,12 @@ macro_rules! define_maps {
             $($(#[$attr])* $name($K)),*
         }
 
+        #[allow(bad_style)]
+        #[derive(Clone, Debug, PartialEq, Eq)]
+        pub enum QueryMsg {
+            $($name(Option<String>)),*
+        }
+
         impl<$tcx> Query<$tcx> {
             pub fn describe(&self, tcx: TyCtxt) -> String {
                 match *self {
@@ -581,10 +637,30 @@ macro_rules! define_maps {
                        key,
                        span);
 
-                if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) {
-                    tcx.dep_graph.read_index(dep_node_index);
-                    return Ok(f(result));
+                profq_msg!(tcx,
+                    ProfileQueriesMsg::QueryBegin(
+                        span.clone(),
+                        QueryMsg::$name(profq_key!(tcx, key))
+                    )
+                );
+
+                if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
+                    if let Some(ref d) = value.diagnostics {
+                        if !d.emitted_diagnostics.get() {
+                            d.emitted_diagnostics.set(true);
+                            let handle = tcx.sess.diagnostic();
+                            for diagnostic in d.diagnostics.iter() {
+                                DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone())
+                                    .emit();
+                            }
+                        }
+                    }
+                    profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                    tcx.dep_graph.read_index(value.index);
+                    return Ok(f(&value.value));
                 }
+                // else, we are going to run the provider:
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
 
                 // FIXME(eddyb) Get more valid Span's on queries.
                 // def_span guard is necessary to prevent a recursive loop,
@@ -593,40 +669,60 @@ macro_rules! define_maps {
                     span = key.default_span(tcx)
                 }
 
-                let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
+                let res = tcx.cycle_check(span, Query::$name(key), || {
                     let dep_node = Self::to_dep_node(tcx, &key);
 
-                    if dep_node.kind.is_anon() {
-                        tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                            let provider = tcx.maps.providers[key.map_crate()].$name;
-                            provider(tcx.global_tcx(), key)
-                        })
-                    } else {
-                        fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
-                                                        key: $K)
-                                                        -> $V {
-                            let provider = tcx.maps.providers[key.map_crate()].$name;
-                            provider(tcx.global_tcx(), key)
+                    tcx.sess.diagnostic().track_diagnostics(|| {
+                        if dep_node.kind.is_anon() {
+                            tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                                let provider = tcx.maps.providers[key.map_crate()].$name;
+                                provider(tcx.global_tcx(), key)
+                            })
+                        } else {
+                            fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
+                                                            key: $K)
+                                                            -> $V {
+                                let provider = tcx.maps.providers[key.map_crate()].$name;
+                                provider(tcx.global_tcx(), key)
+                            }
+
+                            tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
                         }
-
-                        tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
-                    }
+                    })
                 })?;
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
+                let ((result, dep_node_index), diagnostics) = res;
 
                 tcx.dep_graph.read_index(dep_node_index);
 
+                let value = QueryValue {
+                    value: result,
+                    index: dep_node_index,
+                    diagnostics: if diagnostics.len() == 0 {
+                        None
+                    } else {
+                        Some(Box::new(QueryDiagnostics {
+                            diagnostics,
+                            emitted_diagnostics: Cell::new(true),
+                        }))
+                    },
+                };
+
                 Ok(f(&tcx.maps
                          .$name
                          .borrow_mut()
                          .map
                          .entry(key)
-                         .or_insert((result, dep_node_index))
-                         .0))
+                         .or_insert(value)
+                         .value))
             }
 
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-                           -> Result<$V, CycleError<'a, $tcx>> {
-                Self::try_get_with(tcx, span, key, Clone::clone)
+                           -> Result<$V, DiagnosticBuilder<'a>> {
+                match Self::try_get_with(tcx, span, key, Clone::clone) {
+                    Ok(e) => Ok(e),
+                    Err(e) => Err(tcx.report_cycle(e)),
+                }
             }
 
             pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
@@ -635,7 +731,7 @@ macro_rules! define_maps {
 
                 match Self::try_get_with(tcx, span, key, |_| ()) {
                     Ok(()) => {}
-                    Err(e) => tcx.report_cycle(e)
+                    Err(e) => tcx.report_cycle(e).emit(),
                 }
             }
         })*
@@ -672,8 +768,8 @@ macro_rules! define_maps {
         impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
             $($(#[$attr])*
             pub fn $name(self, key: $K) -> $V {
-                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| {
-                    self.report_cycle(e);
+                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
+                    e.emit();
                     Value::from_cycle_error(self.global_tcx())
                 })
             })*
@@ -923,6 +1019,8 @@ define_maps! { <'tcx>
     [] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
 
     [] borrowck: BorrowCheck(DefId) -> (),
+    // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead?
+    [] mir_borrowck: MirBorrowCheck(DefId) -> (),
 
     /// Gets a complete map from all types to their inherent impls.
     /// Not meant to be used directly outside of coherence.
@@ -993,6 +1091,8 @@ define_maps! { <'tcx>
 
     [] is_allocator: IsAllocator(DefId) -> bool,
     [] is_panic_runtime: IsPanicRuntime(DefId) -> bool,
+    [] is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool,
+    [] has_global_allocator: HasGlobalAllocator(DefId) -> bool,
 
     [] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 1daabd744ae..6597dccf258 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -131,6 +131,7 @@ pub struct Resolutions {
     pub freevars: FreevarMap,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
     pub export_map: ExportMap,
 }
 
@@ -1684,12 +1685,15 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
         match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
             Ok(tys) => tys,
-            Err(_) => {
+            Err(mut bug) => {
                 debug!("adt_sized_constraint: {:?} is recursive", self);
                 // This should be reported as an error by `check_representable`.
                 //
                 // Consider the type as Sized in the meanwhile to avoid
-                // further errors.
+                // further errors. Delay our `bug` diagnostic here to get
+                // emitted later as well in case we accidentally otherwise don't
+                // emit an error.
+                bug.delay_as_bug();
                 tcx.intern_type_list(&[tcx.types.err])
             }
         }
@@ -1971,7 +1975,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn local_var_name_str(self, id: NodeId) -> InternedString {
         match self.hir.find(id) {
-            Some(hir_map::NodeLocal(pat)) => {
+            Some(hir_map::NodeBinding(pat)) => {
                 match pat.node {
                     hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(),
                     _ => {
@@ -2232,7 +2236,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::InstanceDef::FnPtrShim(..) |
             ty::InstanceDef::Virtual(..) |
             ty::InstanceDef::ClosureOnceShim { .. } |
-            ty::InstanceDef::DropGlue(..) => {
+            ty::InstanceDef::DropGlue(..) |
+            ty::InstanceDef::CloneShim(..) => {
                 self.mir_shims(instance)
             }
         }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 0d9ef8196c7..c035817d66d 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -253,7 +253,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
             let substs = relation.relate(&a.substs, &b.substs)?;
             Ok(ty::ExistentialProjection {
                 item_def_id: a.item_def_id,
-                substs: substs,
+                substs,
                 ty,
             })
         }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 48ace804995..e41eb079b37 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -137,7 +137,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> {
         tcx.lift(&self.substs).map(|substs| {
             ty::ProjectionTy {
                 item_def_id: self.item_def_id,
-                substs: substs,
+                substs,
             }
         })
     }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index b42180b288b..8d6b7b7ac9f 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -569,7 +569,7 @@ impl<'a, 'tcx> ProjectionTy<'tcx> {
     pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> {
         let def_id = tcx.associated_item(self.item_def_id).container.id();
         ty::TraitRef {
-            def_id: def_id,
+            def_id,
             substs: self.substs,
         }
     }
@@ -739,7 +739,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
 ///
 /// The process of doing that is called "skolemization". The bound regions
 /// are replaced by skolemized markers, which don't satisfy any relation
-/// not explicity provided.
+/// not explicitly provided.
 ///
 /// There are 2 kinds of skolemized regions in rustc: `ReFree` and
 /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed
@@ -874,7 +874,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
     pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> {
         let def_id = tcx.associated_item(self.item_def_id).container.id();
         ty::ExistentialTraitRef{
-            def_id: def_id,
+            def_id,
             substs: self.substs,
         }
     }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 9cd6aa21118..bbbb8611f98 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -1069,11 +1069,15 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let needs_drop = |ty: Ty<'tcx>| -> bool {
         match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
             Ok(v) => v,
-            Err(_) => {
+            Err(mut bug) => {
                 // Cycles should be reported as an error by `check_representable`.
                 //
-                // Consider the type as not needing drop in the meanwhile to avoid
-                // further errors.
+                // Consider the type as not needing drop in the meanwhile to
+                // avoid further errors.
+                //
+                // In case we forgot to emit a bug elsewhere, delay our
+                // diagnostic to get emitted as a compiler bug.
+                bug.delay_as_bug();
                 false
             }
         }
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index c24c583ad1e..6d9e648452f 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -58,7 +58,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                          -> Vec<traits::PredicateObligation<'tcx>>
 {
     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
-    wf.compute_trait_ref(trait_ref);
+    wf.compute_trait_ref(trait_ref, Elaborate::All);
     wf.normalize()
 }
 
@@ -74,7 +74,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     // (*) ok to skip binders, because wf code is prepared for it
     match *predicate {
         ty::Predicate::Trait(ref t) => {
-            wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*)
+            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
         }
         ty::Predicate::Equate(ref t) => {
             wf.compute(t.skip_binder().0);
@@ -114,6 +114,35 @@ struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     out: Vec<traits::PredicateObligation<'tcx>>,
 }
 
+/// Controls whether we "elaborate" supertraits and so forth on the WF
+/// predicates. This is a kind of hack to address #43784. The
+/// underlying problem in that issue was a trait structure like:
+///
+/// ```
+/// trait Foo: Copy { }
+/// trait Bar: Foo { }
+/// impl<T: Bar> Foo for T { }
+/// impl<T> Bar for T { }
+/// ```
+///
+/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
+/// we decide that this is true because `T: Bar` is in the
+/// where-clauses (and we can elaborate that to include `T:
+/// Copy`). This wouldn't be a problem, except that when we check the
+/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
+/// impl. And so nowhere did we check that `T: Copy` holds!
+///
+/// To resolve this, we elaborate the WF requirements that must be
+/// proven when checking impls. This means that (e.g.) the `impl Bar
+/// for T` will be forced to prove not only that `T: Foo` but also `T:
+/// Copy` (which it won't be able to do, because there is no `Copy`
+/// impl for `T`).
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+enum Elaborate {
+    All,
+    None,
+}
+
 impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
     fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
         traits::ObligationCause::new(self.span, self.body_id, code)
@@ -135,12 +164,25 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
 
     /// Pushes the obligations required for `trait_ref` to be WF into
     /// `self.out`.
-    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
+    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
         let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
-        self.out.extend(obligations);
 
         let cause = self.cause(traits::MiscObligation);
         let param_env = self.param_env;
+
+        if let Elaborate::All = elaborate {
+            let predicates = obligations.iter()
+                                        .map(|obligation| obligation.predicate.clone())
+                                        .collect();
+            let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates);
+            let implied_obligations = implied_obligations.map(|pred| {
+                traits::Obligation::new(cause.clone(), param_env, pred)
+            });
+            self.out.extend(implied_obligations);
+        }
+
+        self.out.extend(obligations);
+
         self.out.extend(
             trait_ref.substs.types()
                             .filter(|ty| !ty.has_escaping_regions())
@@ -156,7 +198,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
         // WF and (b) the trait-ref holds.  (It may also be
         // normalizable and be WF that way.)
         let trait_ref = data.trait_ref(self.infcx.tcx);
-        self.compute_trait_ref(&trait_ref);
+        self.compute_trait_ref(&trait_ref, Elaborate::None);
 
         if !data.has_escaping_regions() {
             let predicate = trait_ref.to_predicate();
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 885be8464eb..618a4ed331e 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -19,6 +19,11 @@ use std::iter::repeat;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
+use std::sync::mpsc::{Sender};
+use syntax_pos::{Span};
+use ty::maps::{QueryMsg};
+use dep_graph::{DepNode};
+
 // The name of the associated type for `Fn` return types
 pub const FN_OUTPUT_NAME: &'static str = "Output";
 
@@ -29,6 +34,72 @@ pub struct ErrorReported;
 
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
 
+/// Initialized for -Z profile-queries
+thread_local!(static PROFQ_CHAN: RefCell<Option<Sender<ProfileQueriesMsg>>> = RefCell::new(None));
+
+/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
+#[derive(Clone,Debug)]
+pub struct ProfQDumpParams {
+    /// A base path for the files we will dump
+    pub path:String,
+    /// To ensure that the compiler waits for us to finish our dumps
+    pub ack:Sender<()>,
+    /// toggle dumping a log file with every `ProfileQueriesMsg`
+    pub dump_profq_msg_log:bool,
+}
+
+/// A sequence of these messages induce a trace of query-based incremental compilation.
+/// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
+#[derive(Clone,Debug)]
+pub enum ProfileQueriesMsg {
+    /// begin a timed pass
+    TimeBegin(String),
+    /// end a timed pass
+    TimeEnd,
+    /// begin a task (see dep_graph::graph::with_task)
+    TaskBegin(DepNode),
+    /// end a task
+    TaskEnd,
+    /// begin a new query
+    QueryBegin(Span, 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.
+    ProviderBegin,
+    /// query is satisfied by a provider terminating with a value
+    ProviderEnd,
+    /// dump a record of the queries to the given path
+    Dump(ProfQDumpParams),
+    /// halt the profiling/monitoring background thread
+    Halt
+}
+
+/// If enabled, send a message to the profile-queries thread
+pub fn profq_msg(msg: ProfileQueriesMsg) {
+    PROFQ_CHAN.with(|sender|{
+        if let Some(s) = sender.borrow().as_ref() {
+            s.send(msg).unwrap()
+        } else {
+            // Do nothing.
+            //
+            // FIXME(matthewhammer): Multi-threaded translation phase triggers the panic below.
+            // From backtrace: rustc_trans::back::write::spawn_work::{{closure}}.
+            //
+            // panic!("no channel on which to send profq_msg: {:?}", msg)
+        }
+    })
+}
+
+/// Set channel for profile queries channel
+pub fn profq_set_chan(s: Sender<ProfileQueriesMsg>) -> bool {
+    PROFQ_CHAN.with(|chan|{
+        if chan.borrow().is_none() {
+            *chan.borrow_mut() = Some(s);
+            true
+        } else { false }
+    })
+}
+
 /// Read the current depth of `time()` calls. This is used to
 /// encourage indentation across threads.
 pub fn time_depth() -> usize {
@@ -53,9 +124,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
         r
     });
 
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeBegin(what.to_string()))
+    };
     let start = Instant::now();
     let rv = f();
     let dur = start.elapsed();
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeEnd)
+    };
 
     print_time_passes_entry_internal(what, dur);
 
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index 78b07a33389..f99c6a29ff0 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -36,9 +36,9 @@ pub fn modify(sess: &ParseSess,
               krate: Crate,
               handler: &rustc_errors::Handler) -> ast::Crate {
     ExpandAllocatorDirectives {
-        handler: handler,
-        sess: sess,
-        resolver: resolver,
+        handler,
+        sess,
+        resolver,
         found: false,
     }.fold_crate(krate)
 }
@@ -88,7 +88,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
         };
         let ecfg = ExpansionConfig::default(name.to_string());
         let mut f = AllocFnFactory {
-            span: span,
+            span,
             kind: AllocatorKind::Global,
             global: item.ident,
             alloc: Ident::from_str("alloc"),
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index d0ea40d1e36..e17fce5a2ec 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(warnings)]
+
 #![feature(rustc_private)]
 
 extern crate rustc;
@@ -22,61 +24,51 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
         name: "alloc",
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "oom",
         inputs: &[AllocatorTy::AllocErr],
         output: AllocatorTy::Bang,
-        is_unsafe: false,
     },
     AllocatorMethod {
         name: "dealloc",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
         output: AllocatorTy::Unit,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "usable_size",
         inputs: &[AllocatorTy::LayoutRef],
         output: AllocatorTy::UsizePair,
-        is_unsafe: false,
     },
     AllocatorMethod {
         name: "realloc",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "alloc_zeroed",
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "alloc_excess",
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultExcess,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "realloc_excess",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
         output: AllocatorTy::ResultExcess,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "grow_in_place",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
         output: AllocatorTy::ResultUnit,
-        is_unsafe: true,
     },
     AllocatorMethod {
         name: "shrink_in_place",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
         output: AllocatorTy::ResultUnit,
-        is_unsafe: true,
     },
 ];
 
@@ -84,7 +76,6 @@ pub struct AllocatorMethod {
     pub name: &'static str,
     pub inputs: &'static [AllocatorTy],
     pub output: AllocatorTy,
-    pub is_unsafe: bool,
 }
 
 pub enum AllocatorTy {
diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs
index 3545a77c75d..124c840cc56 100644
--- a/src/librustc_apfloat/ieee.rs
+++ b/src/librustc_apfloat/ieee.rs
@@ -460,18 +460,15 @@ impl<S: Semantics> fmt::Display for IeeeFloat<S> {
             // rem <- sig % 10
             // sig <- sig / 10
             let mut rem = 0;
-            for limb in sig.iter_mut().rev() {
-                // We don't have an integer doubly wide than Limb,
-                // so we have to split the divrem on two halves.
-                const HALF_BITS: usize = LIMB_BITS / 2;
-                let mut halves = [*limb & ((1 << HALF_BITS) - 1), *limb >> HALF_BITS];
-                for half in halves.iter_mut().rev() {
-                    *half |= rem << HALF_BITS;
-                    rem = *half % 10;
-                    *half /= 10;
-                }
-                *limb = halves[0] | (halves[1] << HALF_BITS);
-            }
+
+            // Use 64-bit division and remainder, with 32-bit chunks from sig.
+            sig::each_chunk(&mut sig, 32, |chunk| {
+                let chunk = chunk as u32;
+                let combined = ((rem as u64) << 32) | (chunk as u64);
+                rem = (combined % 10) as u8;
+                (combined / 10) as u32 as Limb
+            });
+
             // Reduce the sigificand to avoid wasting time dividing 0's.
             while sig.last() == Some(&0) {
                 sig.pop();
@@ -491,7 +488,7 @@ impl<S: Semantics> fmt::Display for IeeeFloat<S> {
                 exp += 1;
             } else {
                 in_trail = false;
-                buffer.push(b'0' + digit as u8);
+                buffer.push(b'0' + digit);
             }
         }
 
@@ -2065,7 +2062,7 @@ impl<S: Semantics> IeeeFloat<S> {
         };
 
         // Attempt dec_sig * 10^dec_exp with increasing precision.
-        let mut attempt = 1;
+        let mut attempt = 0;
         loop {
             let calc_precision = (LIMB_BITS << attempt) - 1;
             attempt += 1;
@@ -2310,6 +2307,17 @@ mod sig {
         limbs.iter().all(|&l| l == 0)
     }
 
+    /// One, not zero, based LSB. That is, returns 0 for a zeroed significand.
+    pub(super) fn olsb(limbs: &[Limb]) -> usize {
+        for i in 0..limbs.len() {
+            if limbs[i] != 0 {
+                return i * LIMB_BITS + limbs[i].trailing_zeros() as usize + 1;
+            }
+        }
+
+        0
+    }
+
     /// One, not zero, based MSB. That is, returns 0 for a zeroed significand.
     pub(super) fn omsb(limbs: &[Limb]) -> usize {
         for i in (0..limbs.len()).rev() {
@@ -2468,6 +2476,20 @@ mod sig {
         }
     }
 
+    /// For every consecutive chunk of `bits` bits from `limbs`,
+    /// going from most significant to the least significant bits,
+    /// call `f` to transform those bits and store the result back.
+    pub(super) fn each_chunk<F: FnMut(Limb) -> Limb>(limbs: &mut [Limb], bits: usize, mut f: F) {
+        assert_eq!(LIMB_BITS % bits, 0);
+        for limb in limbs.iter_mut().rev() {
+            let mut r = 0;
+            for i in (0..LIMB_BITS / bits).rev() {
+                r |= f((*limb >> (i * bits)) & ((1 << bits) - 1)) << (i * bits);
+            }
+            *limb = r;
+        }
+    }
+
     /// Increment in-place, return the carry flag.
     pub(super) fn increment(dst: &mut [Limb]) -> Limb {
         for x in dst {
@@ -2686,10 +2708,6 @@ mod sig {
         divisor: &mut [Limb],
         precision: usize,
     ) -> Loss {
-        // Zero the quotient before setting bits in it.
-        for x in &mut quotient[..limbs_for_bits(precision)] {
-            *x = 0;
-        }
 
         // Normalize the divisor.
         let bits = precision - omsb(divisor);
@@ -2700,6 +2718,13 @@ mod sig {
         let bits = precision - omsb(dividend);
         shift_left(dividend, exp, bits);
 
+        // Division by 1.
+        let olsb_divisor = olsb(divisor);
+        if olsb_divisor == precision {
+            quotient.copy_from_slice(dividend);
+            return Loss::ExactlyZero;
+        }
+
         // Ensure the dividend >= divisor initially for the loop below.
         // Incidentally, this means that the division loop below is
         // guaranteed to set the integer bit to one.
@@ -2708,6 +2733,58 @@ mod sig {
             assert_ne!(cmp(dividend, divisor), Ordering::Less)
         }
 
+        // Helper for figuring out the lost fraction.
+        let lost_fraction = |dividend: &[Limb], divisor: &[Limb]| {
+            match cmp(dividend, divisor) {
+                Ordering::Greater => Loss::MoreThanHalf,
+                Ordering::Equal => Loss::ExactlyHalf,
+                Ordering::Less => {
+                    if is_all_zeros(dividend) {
+                        Loss::ExactlyZero
+                    } else {
+                        Loss::LessThanHalf
+                    }
+                }
+            }
+        };
+
+        // Try to perform a (much faster) short division for small divisors.
+        let divisor_bits = precision - (olsb_divisor - 1);
+        macro_rules! try_short_div {
+            ($W:ty, $H:ty, $half:expr) => {
+                if divisor_bits * 2 <= $half {
+                    // Extract the small divisor.
+                    let _: Loss = shift_right(divisor, &mut 0, olsb_divisor - 1);
+                    let divisor = divisor[0] as $H as $W;
+
+                    // Shift the dividend to produce a quotient with the unit bit set.
+                    let top_limb = *dividend.last().unwrap();
+                    let mut rem = (top_limb >> (LIMB_BITS - (divisor_bits - 1))) as $H;
+                    shift_left(dividend, &mut 0, divisor_bits - 1);
+
+                    // Apply short division in place on $H (of $half bits) chunks.
+                    each_chunk(dividend, $half, |chunk| {
+                        let chunk = chunk as $H;
+                        let combined = ((rem as $W) << $half) | (chunk as $W);
+                        rem = (combined % divisor) as $H;
+                        (combined / divisor) as $H as Limb
+                    });
+                    quotient.copy_from_slice(dividend);
+
+                    return lost_fraction(&[(rem as Limb) << 1], &[divisor as Limb]);
+                }
+            }
+        }
+
+        try_short_div!(u32, u16, 16);
+        try_short_div!(u64, u32, 32);
+        try_short_div!(u128, u64, 64);
+
+        // Zero the quotient before setting bits in it.
+        for x in &mut quotient[..limbs_for_bits(precision)] {
+            *x = 0;
+        }
+
         // Long division.
         for bit in (0..precision).rev() {
             if cmp(dividend, divisor) != Ordering::Less {
@@ -2717,17 +2794,6 @@ mod sig {
             shift_left(dividend, &mut 0, 1);
         }
 
-        // Figure out the lost fraction.
-        match cmp(dividend, divisor) {
-            Ordering::Greater => Loss::MoreThanHalf,
-            Ordering::Equal => Loss::ExactlyHalf,
-            Ordering::Less => {
-                if is_all_zeros(dividend) {
-                    Loss::ExactlyZero
-                } else {
-                    Loss::LessThanHalf
-                }
-            }
-        }
+        lost_fraction(dividend, divisor)
     }
 }
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index d9dbf787856..d4a02065761 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -39,7 +39,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_apfloat"]
 #![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/")]
diff --git a/src/librustc_back/dynamic_lib.rs b/src/librustc_back/dynamic_lib.rs
index e6f305c22b2..1b42fa03a4f 100644
--- a/src/librustc_back/dynamic_lib.rs
+++ b/src/librustc_back/dynamic_lib.rs
@@ -12,9 +12,8 @@
 //!
 //! A simple wrapper over the platform's dynamic library facilities
 
-use std::env;
-use std::ffi::{CString, OsString};
-use std::path::{Path, PathBuf};
+use std::ffi::CString;
+use std::path::Path;
 
 pub struct DynamicLibrary {
     handle: *mut u8
@@ -43,24 +42,6 @@ impl DynamicLibrary {
         }
     }
 
-    /// Prepends a path to this process's search path for dynamic libraries
-    pub fn prepend_search_path(path: &Path) {
-        let mut search_path = DynamicLibrary::search_path();
-        search_path.insert(0, path.to_path_buf());
-        env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path));
-    }
-
-    /// From a slice of paths, create a new vector which is suitable to be an
-    /// environment variable for this platforms dylib search path.
-    pub fn create_path(path: &[PathBuf]) -> OsString {
-        let mut newvar = OsString::new();
-        for (i, path) in path.iter().enumerate() {
-            if i > 0 { newvar.push(DynamicLibrary::separator()); }
-            newvar.push(path);
-        }
-        return newvar;
-    }
-
     /// Returns the environment variable for this process's dynamic library
     /// search path
     pub fn envvar() -> &'static str {
@@ -75,19 +56,6 @@ impl DynamicLibrary {
         }
     }
 
-    fn separator() -> &'static str {
-        if cfg!(windows) { ";" } else { ":" }
-    }
-
-    /// Returns the current search path for dynamic libraries being used by this
-    /// process
-    pub fn search_path() -> Vec<PathBuf> {
-        match env::var_os(DynamicLibrary::envvar()) {
-            Some(var) => env::split_paths(&var).collect(),
-            None => Vec::new(),
-        }
-    }
-
     /// Accesses the value at the symbol of the dynamic library.
     pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
         // This function should have a lifetime constraint of 'a on
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index 55b39f22670..6a9833d3784 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -21,9 +21,6 @@
 //! one that doesn't; the one that doesn't might get decent parallel
 //! build speedups.
 
-#![crate_name = "rustc_back"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs
index 2e7d30d969e..4b02d0b60b8 100644
--- a/src/librustc_back/target/apple_ios_base.rs
+++ b/src/librustc_back/target/apple_ios_base.rs
@@ -97,7 +97,7 @@ pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
         cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
-        pre_link_args: pre_link_args,
+        pre_link_args,
         has_elf_tls: false,
         .. super::apple_base::opts()
     })
diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs
index 21410dcd412..112f424f7a8 100644
--- a/src/librustc_back/target/haiku_base.rs
+++ b/src/librustc_back/target/haiku_base.rs
@@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
         target_family: Some("unix".to_string()),
         relro_level: RelroLevel::Full,
         linker_is_gnu: true,
-        no_integrated_as: true,
         .. Default::default()
     }
 }
diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_back/target/l4re_base.rs
index 998183d4015..31d428d2668 100644
--- a/src/librustc_back/target/l4re_base.rs
+++ b/src/librustc_back/target/l4re_base.rs
@@ -12,21 +12,71 @@ use PanicStrategy;
 use LinkerFlavor;
 use target::{LinkArgs, TargetOptions};
 use std::default::Default;
+use std::env;
+use std::process::Command;
 
-pub fn opts() -> TargetOptions {
+// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
+// that a few files also come from L4Re, for these, the function shouldn't be
+// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway.
+fn get_path_or(filename: &str) -> String {
+    let child = Command::new("gcc")
+        .arg(format!("-print-file-name={}", filename)).output()
+        .expect("Failed to execute GCC");
+    String::from_utf8(child.stdout)
+        .expect("Couldn't read path from GCC").trim().into()
+}
+
+pub fn opts() -> Result<TargetOptions, String> {
+    let l4re_lib_path = env::var_os("L4RE_LIBDIR").ok_or("Unable to find L4Re \
+        library directory: L4RE_LIBDIR not set.")?.into_string().unwrap();
     let mut pre_link_args = LinkArgs::new();
     pre_link_args.insert(LinkerFlavor::Ld, vec![
-            "-nostdlib".to_string(),
+        format!("-T{}/main_stat.ld", l4re_lib_path),
+        "--defsym=__executable_start=0x01000000".to_string(),
+        "--defsym=__L4_KIP_ADDR__=0x6ffff000".to_string(),
+        format!("{}/crt1.o", l4re_lib_path),
+        format!("{}/crti.o", l4re_lib_path),
+        get_path_or("crtbeginT.o"),
+    ]);
+    let mut post_link_args = LinkArgs::new();
+    post_link_args.insert(LinkerFlavor::Ld, vec![
+        format!("{}/l4f/libpthread.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sig.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sig_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_socket_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_fs_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sem_noop.a", l4re_lib_path),
+        format!("{}/l4f/libl4re-vfs.o.a", l4re_lib_path),
+        format!("{}/l4f/lib4re.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-util.a", l4re_lib_path),
+        format!("{}/l4f/libc_support_misc.a", l4re_lib_path),
+        format!("{}/l4f/libsupc++.a", l4re_lib_path),
+        format!("{}/l4f/lib4shmc.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-c.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-c-util.a", l4re_lib_path),
+        get_path_or("libgcc_eh.a"),
+        format!("{}/l4f/libdl.a", l4re_lib_path),
+        "--start-group".to_string(),
+        format!("{}/l4f/libl4util.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_l4re.a", l4re_lib_path),
+        format!("{}/l4f/libuc_c.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_l4refile.a", l4re_lib_path),
+        "--end-group".to_string(),
+        format!("{}/l4f/libl4sys.a", l4re_lib_path),
+        "-gc-sections".to_string(),
+        get_path_or("crtend.o"),
+        format!("{}/crtn.o", l4re_lib_path),
     ]);
 
-    TargetOptions {
+    Ok(TargetOptions {
         executables: true,
         has_elf_tls: false,
-        exe_allocation_crate: Some("alloc_system".to_string()),
+        exe_allocation_crate: None,
         panic_strategy: PanicStrategy::Abort,
         linker: "ld".to_string(),
-        pre_link_args: pre_link_args,
+        pre_link_args,
+        post_link_args,
         target_family: Some("unix".to_string()),
         .. Default::default()
-    }
+    })
 }
diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs
index f4265e0eb14..51eeae50e22 100644
--- a/src/librustc_back/target/le32_unknown_nacl.rs
+++ b/src/librustc_back/target/le32_unknown_nacl.rs
@@ -25,8 +25,8 @@ pub fn target() -> TargetResult {
         linker: "pnacl-clang".to_string(),
         ar: "pnacl-ar".to_string(),
 
-        pre_link_args: pre_link_args,
-        post_link_args: post_link_args,
+        pre_link_args,
+        post_link_args,
         dynamic_linking: false,
         executables: true,
         exe_suffix: ".pexe".to_string(),
diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_back/target/linux_musl_base.rs
index 236f2c1ef0a..6e5e139715c 100644
--- a/src/librustc_back/target/linux_musl_base.rs
+++ b/src/librustc_back/target/linux_musl_base.rs
@@ -60,15 +60,10 @@ pub fn opts() -> TargetOptions {
     base.pre_link_objects_exe.push("crti.o".to_string());
     base.post_link_objects.push("crtn.o".to_string());
 
-    // MUSL support doesn't currently include dynamic linking, so there's no
-    // need for dylibs or rpath business. Additionally `-pie` is incompatible
-    // with `-static`, so we can't pass `-pie`.
-    base.dynamic_linking = false;
-    base.has_rpath = false;
-    base.position_independent_executables = false;
-
     // These targets statically link libc by default
     base.crt_static_default = true;
+    // These targets allow the user to choose between static and dynamic linking.
+    base.crt_static_respected = true;
 
     base
 }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 08b94d5a01c..130e1b695db 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -416,8 +416,12 @@ pub struct TargetOptions {
     /// ABIs are considered to be supported on all platforms and cannot be blacklisted.
     pub abi_blacklist: Vec<Abi>,
 
+    /// Whether or not linking dylibs to a static CRT is allowed.
+    pub crt_static_allows_dylibs: bool,
     /// Whether or not the CRT is statically linked by default.
     pub crt_static_default: bool,
+    /// Whether or not crt-static is respected by the compiler (or is a no-op).
+    pub crt_static_respected: bool,
 
     /// Whether or not stack probes (__rust_probestack) are enabled
     pub stack_probes: bool,
@@ -478,7 +482,9 @@ impl Default for TargetOptions {
             max_atomic_width: None,
             panic_strategy: PanicStrategy::Unwind,
             abi_blacklist: vec![],
+            crt_static_allows_dylibs: false,
             crt_static_default: false,
+            crt_static_respected: false,
             stack_probes: false,
         }
     }
@@ -714,7 +720,9 @@ impl Target {
         key!(max_atomic_width, Option<u64>);
         key!(min_atomic_width, Option<u64>);
         try!(key!(panic_strategy, PanicStrategy));
+        key!(crt_static_allows_dylibs, bool);
         key!(crt_static_default, bool);
+        key!(crt_static_respected, bool);
         key!(stack_probes, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
@@ -902,7 +910,9 @@ impl ToJson for Target {
         target_option_val!(min_atomic_width);
         target_option_val!(max_atomic_width);
         target_option_val!(panic_strategy);
+        target_option_val!(crt_static_allows_dylibs);
         target_option_val!(crt_static_default);
+        target_option_val!(crt_static_respected);
         target_option_val!(stack_probes);
 
         if default.abi_blacklist != self.options.abi_blacklist {
diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs
index 2eae0a12408..c7915d4de72 100644
--- a/src/librustc_back/target/redox_base.rs
+++ b/src/librustc_back/target/redox_base.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {LinkerFlavor, PanicStrategy};
+use LinkerFlavor;
 use target::{LinkArgs, TargetOptions};
 use std::default::Default;
 
@@ -37,7 +37,6 @@ pub fn opts() -> TargetOptions {
         target_family: None,
         linker_is_gnu: true,
         has_elf_tls: true,
-        panic_strategy: PanicStrategy::Abort,
         .. Default::default()
     }
 }
diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs
index db47040bf3a..42ab1940404 100644
--- a/src/librustc_back/target/wasm32_experimental_emscripten.rs
+++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs
@@ -38,7 +38,7 @@ pub fn target() -> Result<Target, String> {
         obj_is_bitcode: true,
         is_like_emscripten: true,
         max_atomic_width: Some(32),
-        post_link_args: post_link_args,
+        post_link_args,
         target_family: Some("unix".to_string()),
         .. Default::default()
     };
diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs
index f5fb63038e9..a0a2699d8f9 100644
--- a/src/librustc_back/target/wasm32_unknown_emscripten.rs
+++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs
@@ -34,7 +34,7 @@ pub fn target() -> Result<Target, String> {
         obj_is_bitcode: true,
         is_like_emscripten: true,
         max_atomic_width: Some(32),
-        post_link_args: post_link_args,
+        post_link_args,
         target_family: Some("unix".to_string()),
         .. Default::default()
     };
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs
index 9bde24a28dd..e6aa745d54e 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_back/target/windows_base.rs
@@ -78,7 +78,7 @@ pub fn opts() -> TargetOptions {
         target_family: Some("windows".to_string()),
         is_like_windows: true,
         allows_weak_linkage: false,
-        pre_link_args: pre_link_args,
+        pre_link_args,
         pre_link_objects_exe: vec![
             "crt2.o".to_string(),    // mingw C runtime initialization for executables
             "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
@@ -87,7 +87,7 @@ pub fn opts() -> TargetOptions {
             "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
             "rsbegin.o".to_string(),
         ],
-        late_link_args: late_link_args,
+        late_link_args,
         post_link_objects: vec![
             "rsend.o".to_string()
         ],
diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs
index c07321e418e..42a4e6f5f11 100644
--- a/src/librustc_back/target/windows_msvc_base.rs
+++ b/src/librustc_back/target/windows_msvc_base.rs
@@ -63,6 +63,8 @@ pub fn opts() -> TargetOptions {
         is_like_windows: true,
         is_like_msvc: true,
         pre_link_args: args,
+        crt_static_allows_dylibs: true,
+        crt_static_respected: true,
 
         .. Default::default()
     }
diff --git a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs b/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs
index b447f8a989d..99d3171e1c0 100644
--- a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs
+++ b/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs
@@ -12,7 +12,7 @@ use LinkerFlavor;
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
-    let mut base = super::l4re_base::opts();
+    let mut base = super::l4re_base::opts()?;
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
 
diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs
index e3e89223f2d..8ffaddd7c29 100644
--- a/src/librustc_back/tempdir.rs
+++ b/src/librustc_back/tempdir.rs
@@ -95,15 +95,6 @@ impl TempDir {
         self.path.as_ref().unwrap()
     }
 
-    /// Close and remove the temporary directory
-    ///
-    /// Although `TempDir` removes the directory on drop, in the destructor
-    /// any errors are ignored. To detect errors cleaning up the temporary
-    /// directory, call `close` instead.
-    pub fn close(mut self) -> io::Result<()> {
-        self.cleanup_dir()
-    }
-
     fn cleanup_dir(&mut self) -> io::Result<()> {
         match self.path {
             Some(ref p) => fs::remove_dir_all(p),
diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs
index 73125655792..eb47144d1f9 100644
--- a/src/librustc_bitflags/lib.rs
+++ b/src/librustc_bitflags/lib.rs
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 
-#![crate_name = "rustc_bitflags"]
-#![crate_type = "rlib"]
 #![no_std]
 #![deny(warnings)]
 
diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml
index af99c0e9387..25f02537490 100644
--- a/src/librustc_borrowck/Cargo.toml
+++ b/src/librustc_borrowck/Cargo.toml
@@ -15,6 +15,5 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 graphviz = { path = "../libgraphviz" }
 rustc = { path = "../librustc" }
-rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index c34bf4c3d28..4058f3198af 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -29,6 +29,7 @@ use rustc::ty::{self, TyCtxt};
 use syntax::ast;
 use syntax_pos::Span;
 use rustc::hir;
+use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
 
 use std::rc::Rc;
 
@@ -194,10 +195,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let def_id = bccx.tcx.hir.body_owner_def_id(body.id());
     let param_env = bccx.tcx.param_env(def_id);
     let mut clcx = CheckLoanCtxt {
-        bccx: bccx,
-        dfcx_loans: dfcx_loans,
-        move_data: move_data,
-        all_loans: all_loans,
+        bccx,
+        dfcx_loans,
+        move_data,
+        all_loans,
         param_env,
     };
     euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables)
@@ -465,10 +466,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
 
             let mut err = match (new_loan.kind, old_loan.kind) {
                 (ty::MutBorrow, ty::MutBorrow) => {
-                    let mut err = struct_span_err!(self.bccx, new_loan.span, E0499,
-                                                      "cannot borrow `{}`{} as mutable \
-                                                      more than once at a time",
-                                                      nl, new_loan_msg);
+                    let mut err = self.bccx.cannot_mutably_borrow_multiply(
+                        new_loan.span, &nl, &new_loan_msg, Origin::Ast);
 
                     if new_loan.span == old_loan.span {
                         // Both borrows are happening in the same place
@@ -496,10 +495,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 }
 
                 (ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
-                    let mut err = struct_span_err!(self.bccx, new_loan.span, E0524,
-                                     "two closures require unique access to `{}` \
-                                      at the same time",
-                                     nl);
+                    let mut err = self.bccx.cannot_uniquely_borrow_by_two_closures(
+                        new_loan.span, &nl, Origin::Ast);
                     err.span_label(
                             old_loan.span,
                             "first closure is constructed here");
@@ -513,10 +510,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 }
 
                 (ty::UniqueImmBorrow, _) => {
-                    let mut err = struct_span_err!(self.bccx, new_loan.span, E0500,
-                                                   "closure requires unique access to `{}` \
-                                                   but {} is already borrowed{}",
-                                                   nl, ol_pronoun, old_loan_msg);
+                    let mut err = self.bccx.cannot_uniquely_borrow_by_one_closure(
+                        new_loan.span, &nl, &ol_pronoun, &old_loan_msg, Origin::Ast);
                     err.span_label(
                             new_loan.span,
                             format!("closure construction occurs here{}", new_loan_msg));
@@ -530,10 +525,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 }
 
                 (_, ty::UniqueImmBorrow) => {
-                    let mut err = struct_span_err!(self.bccx, new_loan.span, E0501,
-                                                   "cannot borrow `{}`{} as {} because \
-                                                   previous closure requires unique access",
-                                                   nl, new_loan_msg, new_loan.kind.to_user_str());
+                    let new_loan_str = &new_loan.kind.to_user_str();
+                    let mut err = self.bccx.cannot_reborrow_already_uniquely_borrowed(
+                        new_loan.span, &nl, &new_loan_msg, new_loan_str, Origin::Ast);
                     err.span_label(
                             new_loan.span,
                             format!("borrow occurs here{}", new_loan_msg));
@@ -547,15 +541,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                 }
 
                 (..) => {
-                    let mut err = struct_span_err!(self.bccx, new_loan.span, E0502,
-                                                   "cannot borrow `{}`{} as {} because \
-                                                   {} is also borrowed as {}{}",
-                                                   nl,
-                                                   new_loan_msg,
-                                                   new_loan.kind.to_user_str(),
-                                                   ol_pronoun,
-                                                   old_loan.kind.to_user_str(),
-                                                   old_loan_msg);
+                    let mut err = self.bccx.cannot_reborrow_already_borrowed(
+                        new_loan.span,
+                        &nl, &new_loan_msg, &new_loan.kind.to_user_str(),
+                        &ol_pronoun, &old_loan.kind.to_user_str(), &old_loan_msg, Origin::Ast);
                     err.span_label(
                             new_loan.span,
                             format!("{} borrow occurs here{}",
@@ -645,9 +634,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
             UseOk => { }
             UseWhileBorrowed(loan_path, loan_span) => {
-                struct_span_err!(self.bccx, span, E0503,
-                                 "cannot use `{}` because it was mutably borrowed",
-                                 &self.bccx.loan_path_to_string(copy_path))
+                let desc = self.bccx.loan_path_to_string(copy_path);
+                self.bccx.cannot_use_when_mutably_borrowed(span, &desc, Origin::Ast)
                     .span_label(loan_span,
                                format!("borrow of `{}` occurs here",
                                        &self.bccx.loan_path_to_string(&loan_path))
@@ -673,9 +661,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             UseWhileBorrowed(loan_path, loan_span) => {
                 let mut err = match move_kind {
                     move_data::Captured => {
-                        let mut err = struct_span_err!(self.bccx, span, E0504,
-                                         "cannot move `{}` into closure because it is borrowed",
-                                         &self.bccx.loan_path_to_string(move_path));
+                        let mut err = self.bccx.cannot_move_into_closure(
+                            span, &self.bccx.loan_path_to_string(move_path), Origin::Ast);
                         err.span_label(
                             loan_span,
                             format!("borrow of `{}` occurs here",
@@ -690,9 +677,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                     move_data::Declared |
                     move_data::MoveExpr |
                     move_data::MovePat => {
-                        let mut err = struct_span_err!(self.bccx, span, E0505,
-                                         "cannot move out of `{}` because it is borrowed",
-                                         &self.bccx.loan_path_to_string(move_path));
+                        let desc = self.bccx.loan_path_to_string(move_path);
+                        let mut err = self.bccx.cannot_move_when_borrowed(span, &desc, Origin::Ast);
                         err.span_label(
                             loan_span,
                             format!("borrow of `{}` occurs here",
@@ -874,9 +860,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                                    span: Span,
                                    loan_path: &LoanPath<'tcx>,
                                    loan: &Loan) {
-        struct_span_err!(self.bccx, span, E0506,
-                         "cannot assign to `{}` because it is borrowed",
-                         self.bccx.loan_path_to_string(loan_path))
+        self.bccx.cannot_assign_to_borrowed(
+            span, &self.bccx.loan_path_to_string(loan_path), Origin::Ast)
             .span_label(loan.span,
                        format!("borrow of `{}` occurs here",
                                self.bccx.loan_path_to_string(loan_path)))
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 3d98c2a23dc..78787627889 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -68,19 +68,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte
                     });
             PatternSource::MatchExpr(e)
         }
-        NodeStmt(ref s) => {
-            // the enclosing statement must be a `let` or something else
-            match s.node {
-                StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        DeclLocal(ref local) => PatternSource::LetDecl(local),
-                        _ => return PatternSource::Other,
-                    }
-                }
-                _ => return PatternSource::Other,
-            }
-        }
-
+        NodeLocal(local) => PatternSource::LetDecl(local),
         _ => return PatternSource::Other,
 
     }
@@ -106,44 +94,13 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     };
     let move_info = GatherMoveInfo {
         id: move_expr_id,
-        kind: kind,
-        cmt: cmt,
+        kind,
+        cmt,
         span_path_opt: None,
     };
     gather_move(bccx, move_data, move_error_collector, move_info);
 }
 
-pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
-                                      move_data: &MoveData<'tcx>,
-                                      _move_error_collector: &mut MoveErrorCollector<'tcx>,
-                                      move_pat: &hir::Pat,
-                                      cmt: mc::cmt<'tcx>,
-                                      mode: euv::MatchMode) {
-    let tcx = bccx.tcx;
-    debug!("gather_match_variant(move_pat={}, cmt={:?}, mode={:?})",
-           move_pat.id, cmt, mode);
-
-    let opt_lp = opt_loan_path(&cmt);
-    match opt_lp {
-        Some(lp) => {
-            match lp.kind {
-                LpDowncast(ref base_lp, _) =>
-                    move_data.add_variant_match(
-                        tcx, lp.clone(), move_pat.id, base_lp.clone(), mode),
-                _ => bug!("should only call gather_match_variant \
-                           for cat_downcast cmt"),
-            }
-        }
-        None => {
-            // We get None when input to match is non-path (e.g.
-            // temporary result like a function call). Since no
-            // loan-path is being matched, no need to record a
-            // downcast.
-            return;
-        }
-    }
-}
-
 pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       move_data: &MoveData<'tcx>,
                                       move_error_collector: &mut MoveErrorCollector<'tcx>,
@@ -163,7 +120,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let move_info = GatherMoveInfo {
         id: move_pat.id,
         kind: MovePat,
-        cmt: cmt,
+        cmt,
         span_path_opt: pat_span_path_opt,
     };
 
diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
index 89c60da3969..22de3c75913 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
@@ -37,10 +37,10 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     debug!("guarantee_lifetime(cmt={:?}, loan_region={:?})",
            cmt, loan_region);
     let ctxt = GuaranteeLifetimeContext {bccx: bccx,
-                                         item_scope: item_scope,
-                                         span: span,
-                                         cause: cause,
-                                         loan_region: loan_region,
+                                         item_scope,
+                                         span,
+                                         cause,
+                                         loan_region,
                                          cmt_original: cmt.clone()};
     ctxt.check(&cmt, None)
 }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 35af83c8ae2..00ebf5de44a 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -41,7 +41,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let def_id = bccx.tcx.hir.body_owner_def_id(body);
     let param_env = bccx.tcx.param_env(def_id);
     let mut glcx = GatherLoanCtxt {
-        bccx: bccx,
+        bccx,
         all_loans: Vec::new(),
         item_ub: region::CodeExtent::Misc(body.node_id),
         move_data: MoveData::new(),
@@ -94,12 +94,6 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> {
                matched_pat,
                cmt,
                mode);
-
-        if let Categorization::Downcast(..) = cmt.cat {
-            gather_moves::gather_match_variant(
-                self.bccx, &self.move_data, &mut self.move_error_collector,
-                matched_pat, cmt, mode);
-        }
     }
 
     fn consume_pat(&mut self,
@@ -230,8 +224,8 @@ fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
             // Only mutable data can be lent as mutable.
             if !cmt.mutbl.is_mutable() {
                 Err(bccx.report(BckError { span: borrow_span,
-                                           cause: cause,
-                                           cmt: cmt,
+                                           cause,
+                                           cmt,
                                            code: err_mutbl }))
             } else {
                 Ok(())
@@ -389,13 +383,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
 
                 Loan {
                     index: self.all_loans.len(),
-                    loan_path: loan_path,
+                    loan_path,
                     kind: req_kind,
-                    gen_scope: gen_scope,
-                    kill_scope: kill_scope,
+                    gen_scope,
+                    kill_scope,
                     span: borrow_span,
-                    restricted_paths: restricted_paths,
-                    cause: cause,
+                    restricted_paths,
+                    cause,
                 }
             }
         };
@@ -423,13 +417,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
             //    let all_loans = &mut *self.all_loans; // FIXME(#5074)
             //    Loan {
             //        index: all_loans.len(),
-            //        loan_path: loan_path,
-            //        cmt: cmt,
+            //        loan_path,
+            //        cmt,
             //        mutbl: ConstMutability,
             //        gen_scope: borrow_id,
-            //        kill_scope: kill_scope,
+            //        kill_scope,
             //        span: borrow_span,
-            //        restrictions: restrictions
+            //        restrictions,
             //    }
         // }
     }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index bfd883be848..57b92eb8f88 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -49,8 +49,8 @@ impl<'tcx> MoveError<'tcx> {
                           move_to: Option<MovePlace<'tcx>>)
                           -> MoveError<'tcx> {
         MoveError {
-            move_from: move_from,
-            move_to: move_to,
+            move_from,
+            move_to,
         }
     }
 }
@@ -153,20 +153,19 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         }
 
         Categorization::Interior(ref b, mc::InteriorElement(ik)) => {
-            match (&b.ty.sty, ik) {
-                (&ty::TySlice(..), _) |
-                (_, Kind::Index) => {
-                    let mut err = struct_span_err!(bccx, move_from.span, E0508,
-                                                   "cannot move out of type `{}`, \
-                                                    a non-copy array",
-                                                   b.ty);
-                    err.span_label(move_from.span, "cannot move out of here");
-                    err
-                }
-                (_, Kind::Pattern) => {
+            let type_name = match (&b.ty.sty, ik) {
+                (&ty::TyArray(_, _), Kind::Index) => "array",
+                (&ty::TySlice(_), _) => "slice",
+                _ => {
                     span_bug!(move_from.span, "this path should not cause illegal move");
-                }
-            }
+                },
+            };
+            let mut err = struct_span_err!(bccx, move_from.span, E0508,
+                                           "cannot move out of type `{}`, \
+                                            a non-copy {}",
+                                           b.ty, type_name);
+            err.span_label(move_from.span, "cannot move out of here");
+            err
         }
 
         Categorization::Downcast(ref b, _) |
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index b7965f81b88..bc01f22d388 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -34,10 +34,10 @@ pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       loan_region: ty::Region<'tcx>)
                                       -> RestrictionResult<'tcx> {
     let ctxt = RestrictionsContext {
-        bccx: bccx,
-        span: span,
-        cause: cause,
-        loan_region: loan_region,
+        bccx,
+        span,
+        cause,
+        loan_region,
     };
 
     ctxt.restrict(cmt)
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 412af05f5bd..38336655f21 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -37,6 +37,8 @@ use rustc::middle::free_region::RegionRelations;
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::maps::Providers;
 
+use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
+
 use std::fmt;
 use std::rc::Rc;
 use std::hash::{Hash, Hasher};
@@ -180,7 +182,7 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc
                                                       id_range,
                                                       body);
 
-    Some(AnalysisData { all_loans: all_loans,
+    Some(AnalysisData { all_loans,
                         loans: loan_dfcx,
                         move_data:flowed_moves })
 }
@@ -218,6 +220,25 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     owner_def_id: DefId,
 }
 
+impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
+    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
+                                                         sp: S,
+                                                         msg: &str,
+                                                         code: &str)
+                                                         -> DiagnosticBuilder<'a>
+    {
+        self.tcx.sess.struct_span_err_with_code(sp, msg, code)
+    }
+
+    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
+                                               sp: S,
+                                               msg: &str)
+                                               -> DiagnosticBuilder<'a>
+    {
+        self.tcx.sess.struct_span_err(sp, msg)
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Loans and loan paths
 
@@ -549,14 +570,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             move_data::Declared => {
                 // If this is an uninitialized variable, just emit a simple warning
                 // and return.
-                struct_span_err!(
-                    self.tcx.sess, use_span, E0381,
-                    "{} of possibly uninitialized variable: `{}`",
-                    verb,
-                    self.loan_path_to_string(lp))
-                .span_label(use_span, format!("use of possibly uninitialized `{}`",
-                    self.loan_path_to_string(lp)))
-                .emit();
+                self.cannot_act_on_uninitialized_variable(use_span,
+                                                          verb,
+                                                          &self.loan_path_to_string(lp),
+                                                          Origin::Ast)
+                    .span_label(use_span, format!("use of possibly uninitialized `{}`",
+                                                  self.loan_path_to_string(lp)))
+                    .emit();
                 return;
             }
             _ => {
@@ -683,10 +703,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                 lp: &LoanPath<'tcx>,
                                                 assign:
                                                 &move_data::Assignment) {
-        let mut err = struct_span_err!(
-            self.tcx.sess, span, E0384,
-            "re-assignment of immutable variable `{}`",
-            self.loan_path_to_string(lp));
+        let mut err = self.cannot_reassign_immutable(span,
+                                                     &self.loan_path_to_string(lp),
+                                                     Origin::Ast);
         err.span_label(span, "re-assignment of immutable variable");
         if span != assign.span {
             err.span_label(assign.span, format!("first assignment to `{}`",
@@ -695,15 +714,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         err.emit();
     }
 
-    pub fn span_err(&self, s: Span, m: &str) {
-        self.tcx.sess.span_err(s, m);
-    }
-
-    pub fn struct_span_err<S: Into<MultiSpan>>(&self, s: S, m: &str)
-                                              -> DiagnosticBuilder<'a> {
-        self.tcx.sess.struct_span_err(s, m)
-    }
-
     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
                                                          s: S,
                                                          msg: &str,
@@ -712,10 +722,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         self.tcx.sess.struct_span_err_with_code(s, msg, code)
     }
 
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, code: &str) {
-        self.tcx.sess.span_err_with_code(s, msg, code);
-    }
-
     fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
         let span = err.span.clone();
 
@@ -897,7 +903,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
 
     fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode {
         let pat = match self.tcx.hir.get(node_id) {
-            hir_map::Node::NodeLocal(pat) => pat,
+            hir_map::Node::NodeBinding(pat) => pat,
             node => bug!("bad node for local: {:?}", node)
         };
 
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index fd80e8320d6..217bd6e6ca1 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -53,10 +53,6 @@ pub struct MoveData<'tcx> {
     /// kill move bits.
     pub path_assignments: RefCell<Vec<Assignment>>,
 
-    /// Enum variant matched within a pattern on some match arm, like
-    /// `SomeStruct{ f: Variant1(x, y) } => ...`
-    pub variant_matches: RefCell<Vec<VariantMatch>>,
-
     /// Assignments to a variable or path, like `x = foo`, but not `x += foo`.
     pub assignee_ids: RefCell<NodeSet>,
 }
@@ -161,21 +157,6 @@ pub struct Assignment {
     pub assignee_id: ast::NodeId,
 }
 
-#[derive(Copy, Clone)]
-pub struct VariantMatch {
-    /// downcast to the variant.
-    pub path: MovePathIndex,
-
-    /// path being downcast to the variant.
-    pub base_path: MovePathIndex,
-
-    /// id where variant's pattern occurs
-    pub id: ast::NodeId,
-
-    /// says if variant established by move (and why), by copy, or by borrow.
-    pub mode: euv::MatchMode
-}
-
 #[derive(Clone, Copy)]
 pub struct MoveDataFlowOperator;
 
@@ -215,7 +196,6 @@ impl<'a, 'tcx> MoveData<'tcx> {
             moves: RefCell::new(Vec::new()),
             path_assignments: RefCell::new(Vec::new()),
             var_assignments: RefCell::new(Vec::new()),
-            variant_matches: RefCell::new(Vec::new()),
             assignee_ids: RefCell::new(NodeSet()),
         }
     }
@@ -310,7 +290,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
                     parent: parent_index,
                     first_move: InvalidMoveIndex,
                     first_child: InvalidMovePathIndex,
-                    next_sibling: next_sibling,
+                    next_sibling,
                 });
 
                 index
@@ -408,9 +388,9 @@ impl<'a, 'tcx> MoveData<'tcx> {
 
         self.moves.borrow_mut().push(Move {
             path: path_index,
-            id: id,
-            kind: kind,
-            next_move: next_move
+            id,
+            kind,
+            next_move,
         });
     }
 
@@ -468,8 +448,8 @@ impl<'a, 'tcx> MoveData<'tcx> {
         let assignment = Assignment {
             path: path_index,
             id: assign_id,
-            span: span,
-            assignee_id: assignee_id,
+            span,
+            assignee_id,
         };
 
         if self.is_var_path(path_index) {
@@ -485,31 +465,6 @@ impl<'a, 'tcx> MoveData<'tcx> {
         }
     }
 
-    /// Adds a new record for a match of `base_lp`, downcast to
-    /// variant `lp`, that occurs at location `pattern_id`.  (One
-    /// should be able to recover the span info from the
-    /// `pattern_id` and the hir_map, I think.)
-    pub fn add_variant_match(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             lp: Rc<LoanPath<'tcx>>,
-                             pattern_id: ast::NodeId,
-                             base_lp: Rc<LoanPath<'tcx>>,
-                             mode: euv::MatchMode) {
-        debug!("add_variant_match(lp={:?}, pattern_id={})",
-               lp, pattern_id);
-
-        let path_index = self.move_path(tcx, lp.clone());
-        let base_path_index = self.move_path(tcx, base_lp.clone());
-
-        let variant_match = VariantMatch {
-            path: path_index,
-            base_path: base_path_index,
-            id: pattern_id,
-            mode: mode,
-        };
-
-        self.variant_matches.borrow_mut().push(variant_match);
-    }
-
     /// Adds the gen/kills for the various moves and
     /// assignments into the provided data flow contexts.
     /// Moves are generated by moves and killed by assignments and
@@ -680,9 +635,9 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
         dfcx_assign.propagate(cfg, body);
 
         FlowedMoveData {
-            move_data: move_data,
-            dfcx_moves: dfcx_moves,
-            dfcx_assign: dfcx_assign,
+            move_data,
+            dfcx_moves,
+            dfcx_assign,
         }
     }
 
diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs
index fea9d0d6f13..1f1fc4cc65f 100644
--- a/src/librustc_borrowck/diagnostics.rs
+++ b/src/librustc_borrowck/diagnostics.rs
@@ -63,27 +63,6 @@ Now that the closure has its own copy of the data, there's no need to worry
 about safety.
 "##,
 
-E0381: r##"
-It is not allowed to use or capture an uninitialized variable. For example:
-
-```compile_fail,E0381
-fn main() {
-    let x: i32;
-    let y = x; // error, use of possibly uninitialized variable
-}
-```
-
-To fix this, ensure that any declared variables are initialized before being
-used. Example:
-
-```
-fn main() {
-    let x: i32 = 0;
-    let y = x; // ok!
-}
-```
-"##,
-
 E0382: r##"
 This error occurs when an attempt is made to use a variable after its contents
 have been moved elsewhere. For example:
@@ -182,28 +161,6 @@ x = Foo { a: 2 };
 ```
 "##,
 
-E0384: r##"
-This error occurs when an attempt is made to reassign an immutable variable.
-For example:
-
-```compile_fail,E0384
-fn main() {
-    let x = 3;
-    x = 5; // error, reassignment of immutable variable
-}
-```
-
-By default, variables in Rust are immutable. To fix this error, add the keyword
-`mut` after the keyword `let` when declaring the variable. For example:
-
-```
-fn main() {
-    let mut x = 3;
-    x = 5;
-}
-```
-"##,
-
 /*E0386: r##"
 This error occurs when an attempt is made to mutate the target of a mutable
 reference stored inside an immutable container.
@@ -360,512 +317,6 @@ fn main() {
 ```
 "##,
 
-E0499: r##"
-A variable was borrowed as mutable more than once. Erroneous code example:
-
-```compile_fail,E0499
-let mut i = 0;
-let mut x = &mut i;
-let mut a = &mut i;
-// error: cannot borrow `i` as mutable more than once at a time
-```
-
-Please note that in rust, you can either have many immutable references, or one
-mutable reference. Take a look at
-https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
-for more information. Example:
-
-
-```
-let mut i = 0;
-let mut x = &mut i; // ok!
-
-// or:
-let mut i = 0;
-let a = &i; // ok!
-let b = &i; // still ok!
-let c = &i; // still ok!
-```
-"##,
-
-E0500: r##"
-A borrowed variable was used in another closure. Example of erroneous code:
-
-```compile_fail
-fn you_know_nothing(jon_snow: &mut i32) {
-    let nights_watch = || {
-        *jon_snow = 2;
-    };
-    let starks = || {
-        *jon_snow = 3; // error: closure requires unique access to `jon_snow`
-                       //        but it is already borrowed
-    };
-}
-```
-
-In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it
-cannot be borrowed by the `starks` closure at the same time. To fix this issue,
-you can put the closure in its own scope:
-
-```
-fn you_know_nothing(jon_snow: &mut i32) {
-    {
-        let nights_watch = || {
-            *jon_snow = 2;
-        };
-    } // At this point, `jon_snow` is free.
-    let starks = || {
-        *jon_snow = 3;
-    };
-}
-```
-
-Or, if the type implements the `Clone` trait, you can clone it between
-closures:
-
-```
-fn you_know_nothing(jon_snow: &mut i32) {
-    let mut jon_copy = jon_snow.clone();
-    let nights_watch = || {
-        jon_copy = 2;
-    };
-    let starks = || {
-        *jon_snow = 3;
-    };
-}
-```
-"##,
-
-E0501: r##"
-This error indicates that a mutable variable is being used while it is still
-captured by a closure. Because the closure has borrowed the variable, it is not
-available for use until the closure goes out of scope.
-
-Note that a capture will either move or borrow a variable, but in this
-situation, the closure is borrowing the variable. Take a look at
-http://rustbyexample.com/fn/closures/capture.html for more information about
-capturing.
-
-Example of erroneous code:
-
-```compile_fail,E0501
-fn inside_closure(x: &mut i32) {
-    // Actions which require unique access
-}
-
-fn outside_closure(x: &mut i32) {
-    // Actions which require unique access
-}
-
-fn foo(a: &mut i32) {
-    let bar = || {
-        inside_closure(a)
-    };
-    outside_closure(a); // error: cannot borrow `*a` as mutable because previous
-                        //        closure requires unique access.
-}
-```
-
-To fix this error, you can place the closure in its own scope:
-
-```
-fn inside_closure(x: &mut i32) {}
-fn outside_closure(x: &mut i32) {}
-
-fn foo(a: &mut i32) {
-    {
-        let bar = || {
-            inside_closure(a)
-        };
-    } // borrow on `a` ends.
-    outside_closure(a); // ok!
-}
-```
-
-Or you can pass the variable as a parameter to the closure:
-
-```
-fn inside_closure(x: &mut i32) {}
-fn outside_closure(x: &mut i32) {}
-
-fn foo(a: &mut i32) {
-    let bar = |s: &mut i32| {
-        inside_closure(s)
-    };
-    outside_closure(a);
-    bar(a);
-}
-```
-
-It may be possible to define the closure later:
-
-```
-fn inside_closure(x: &mut i32) {}
-fn outside_closure(x: &mut i32) {}
-
-fn foo(a: &mut i32) {
-    outside_closure(a);
-    let bar = || {
-        inside_closure(a)
-    };
-}
-```
-"##,
-
-E0502: r##"
-This error indicates that you are trying to borrow a variable as mutable when it
-has already been borrowed as immutable.
-
-Example of erroneous code:
-
-```compile_fail,E0502
-fn bar(x: &mut i32) {}
-fn foo(a: &mut i32) {
-    let ref y = a; // a is borrowed as immutable.
-    bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed
-            //        as immutable
-}
-```
-
-To fix this error, ensure that you don't have any other references to the
-variable before trying to access it mutably:
-
-```
-fn bar(x: &mut i32) {}
-fn foo(a: &mut i32) {
-    bar(a);
-    let ref y = a; // ok!
-}
-```
-
-For more information on the rust ownership system, take a look at
-https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html.
-"##,
-
-E0503: r##"
-A value was used after it was mutably borrowed.
-
-Example of erroneous code:
-
-```compile_fail,E0503
-fn main() {
-    let mut value = 3;
-    // Create a mutable borrow of `value`. This borrow
-    // lives until the end of this function.
-    let _borrow = &mut value;
-    let _sum = value + 1; // error: cannot use `value` because
-                          //        it was mutably borrowed
-}
-```
-
-In this example, `value` is mutably borrowed by `borrow` and cannot be
-used to calculate `sum`. This is not possible because this would violate
-Rust's mutability rules.
-
-You can fix this error by limiting the scope of the borrow:
-
-```
-fn main() {
-    let mut value = 3;
-    // By creating a new block, you can limit the scope
-    // of the reference.
-    {
-        let _borrow = &mut value; // Use `_borrow` inside this block.
-    }
-    // The block has ended and with it the borrow.
-    // You can now use `value` again.
-    let _sum = value + 1;
-}
-```
-
-Or by cloning `value` before borrowing it:
-
-```
-fn main() {
-    let mut value = 3;
-    // We clone `value`, creating a copy.
-    let value_cloned = value.clone();
-    // The mutable borrow is a reference to `value` and
-    // not to `value_cloned`...
-    let _borrow = &mut value;
-    // ... which means we can still use `value_cloned`,
-    let _sum = value_cloned + 1;
-    // even though the borrow only ends here.
-}
-```
-
-You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
-"##,
-
-E0504: r##"
-This error occurs when an attempt is made to move a borrowed variable into a
-closure.
-
-Example of erroneous code:
-
-```compile_fail,E0504
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let fancy_num = FancyNum { num: 5 };
-    let fancy_ref = &fancy_num;
-
-    let x = move || {
-        println!("child function: {}", fancy_num.num);
-        // error: cannot move `fancy_num` into closure because it is borrowed
-    };
-
-    x();
-    println!("main function: {}", fancy_ref.num);
-}
-```
-
-Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
-the closure `x`. There is no way to move a value into a closure while it is
-borrowed, as that would invalidate the borrow.
-
-If the closure can't outlive the value being moved, try using a reference
-rather than moving:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let fancy_num = FancyNum { num: 5 };
-    let fancy_ref = &fancy_num;
-
-    let x = move || {
-        // fancy_ref is usable here because it doesn't move `fancy_num`
-        println!("child function: {}", fancy_ref.num);
-    };
-
-    x();
-
-    println!("main function: {}", fancy_num.num);
-}
-```
-
-If the value has to be borrowed and then moved, try limiting the lifetime of
-the borrow using a scoped block:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let fancy_num = FancyNum { num: 5 };
-
-    {
-        let fancy_ref = &fancy_num;
-        println!("main function: {}", fancy_ref.num);
-        // `fancy_ref` goes out of scope here
-    }
-
-    let x = move || {
-        // `fancy_num` can be moved now (no more references exist)
-        println!("child function: {}", fancy_num.num);
-    };
-
-    x();
-}
-```
-
-If the lifetime of a reference isn't enough, such as in the case of threading,
-consider using an `Arc` to create a reference-counted value:
-
-```
-use std::sync::Arc;
-use std::thread;
-
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let fancy_ref1 = Arc::new(FancyNum { num: 5 });
-    let fancy_ref2 = fancy_ref1.clone();
-
-    let x = thread::spawn(move || {
-        // `fancy_ref1` can be moved and has a `'static` lifetime
-        println!("child thread: {}", fancy_ref1.num);
-    });
-
-    x.join().expect("child thread should finish");
-    println!("main thread: {}", fancy_ref2.num);
-}
-```
-"##,
-
-E0505: r##"
-A value was moved out while it was still borrowed.
-
-Erroneous code example:
-
-```compile_fail,E0505
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(x);
-    }
-}
-```
-
-Here, the function `eat` takes the ownership of `x`. However,
-`x` cannot be moved because it was borrowed to `_ref_to_val`.
-To fix that you can do few different things:
-
-* Try to avoid moving the variable.
-* Release borrow before move.
-* Implement the `Copy` trait on the type.
-
-Examples:
-
-```
-struct Value {}
-
-fn eat(val: &Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(&x); // pass by reference, if it's possible
-    }
-}
-```
-
-Or:
-
-```
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-    }
-    eat(x); // release borrow and then move it.
-}
-```
-
-Or:
-
-```
-#[derive(Clone, Copy)] // implement Copy trait
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(x); // it will be copied here.
-    }
-}
-```
-
-You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
-"##,
-
-E0506: r##"
-This error occurs when an attempt is made to assign to a borrowed value.
-
-Example of erroneous code:
-
-```compile_fail,E0506
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy_num = FancyNum { num: 5 };
-    let fancy_ref = &fancy_num;
-    fancy_num = FancyNum { num: 6 };
-    // error: cannot assign to `fancy_num` because it is borrowed
-
-    println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
-}
-```
-
-Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
-be assigned to a new value as it would invalidate the reference.
-
-Alternatively, we can move out of `fancy_num` into a second `fancy_num`:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy_num = FancyNum { num: 5 };
-    let moved_num = fancy_num;
-    fancy_num = FancyNum { num: 6 };
-
-    println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num);
-}
-```
-
-If the value has to be borrowed, try limiting the lifetime of the borrow using
-a scoped block:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy_num = FancyNum { num: 5 };
-
-    {
-        let fancy_ref = &fancy_num;
-        println!("Ref: {}", fancy_ref.num);
-    }
-
-    // Works because `fancy_ref` is no longer in scope
-    fancy_num = FancyNum { num: 6 };
-    println!("Num: {}", fancy_num.num);
-}
-```
-
-Or by moving the reference into a function:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy_num = FancyNum { num: 5 };
-
-    print_fancy_ref(&fancy_num);
-
-    // Works because function borrow has ended
-    fancy_num = FancyNum { num: 6 };
-    println!("Num: {}", fancy_num.num);
-}
-
-fn print_fancy_ref(fancy_ref: &FancyNum){
-    println!("Ref: {}", fancy_ref.num);
-}
-```
-"##,
-
 E0507: r##"
 You tried to move out of a value which was borrowed. Erroneous code example:
 
@@ -1205,7 +656,6 @@ x.x = Some(&y);
 
 register_diagnostics! {
 //    E0385, // {} in an aliasable location
-    E0524, // two closures require unique access to `..` at the same time
     E0594, // cannot assign to {}
     E0598, // lifetime of {} is too short to guarantee its contents can be...
 }
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 7a63592828f..9bedbfed5db 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_borrowck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -31,17 +28,14 @@ extern crate rustc_errors as errors;
 extern crate graphviz as dot;
 #[macro_use]
 extern crate rustc;
-extern crate rustc_data_structures;
 extern crate rustc_mir;
-extern crate core; // for NonZero
 
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
-pub use borrowck::{AnalysisData, BorrowckCtxt};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
-pub mod diagnostics;
+mod diagnostics;
 
 mod borrowck;
 
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index bae44c0047e..bc9aa9665c1 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -166,8 +166,8 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
         let pattern_arena = TypedArena::new();
 
         f(MatchCheckCtxt {
-            tcx: tcx,
-            module: module,
+            tcx,
+            module,
             pattern_arena: &pattern_arena,
             byte_array_map: FxHashMap(),
         })
@@ -296,7 +296,7 @@ impl<'tcx> Witness<'tcx> {
         let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty);
         self.0.extend(sub_pattern_tys.into_iter().map(|ty| {
             Pattern {
-                ty: ty,
+                ty,
                 span: DUMMY_SP,
                 kind: box PatternKind::Wild,
             }
@@ -344,7 +344,7 @@ impl<'tcx> Witness<'tcx> {
                         if adt.variants.len() > 1 {
                             PatternKind::Variant {
                                 adt_def: adt,
-                                substs: substs,
+                                substs,
                                 variant_index: ctor.variant_index_for_adt(adt),
                                 subpatterns: pats
                             }
@@ -378,7 +378,7 @@ impl<'tcx> Witness<'tcx> {
         };
 
         self.0.push(Pattern {
-            ty: ty,
+            ty,
             span: DUMMY_SP,
             kind: Box::new(pat),
         });
@@ -673,7 +673,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
     let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| {
         Pattern {
-            ty: ty,
+            ty,
             span: DUMMY_SP,
             kind: box PatternKind::Wild,
         }
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index ea7deef4724..2bed1950afc 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -524,7 +524,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
 /// FIXME: this should be done by borrowck.
 fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
     let mut checker = MutationChecker {
-        cx: cx,
+        cx,
     };
     ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_maps, cx.tables)
         .walk_expr(guard);
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 20ca218571c..c7def0b834c 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -379,7 +379,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             tcx,
             param_env: cx.param_env,
             tables: tcx.typeck_tables_of(def_id),
-            substs: substs,
+            substs,
             fn_args: Some(call_args)
           };
           callee_cx.eval(&body.value)?
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 5a61f35ed1c..9fedee80d46 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_const_eval"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -41,7 +38,7 @@ extern crate syntax_pos;
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
-pub mod diagnostics;
+mod diagnostics;
 
 mod eval;
 mod _match;
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index d151e817040..ba79f775ef7 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -407,8 +407,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 }
 
                 PatternKind::Binding {
-                    mutability: mutability,
-                    mode: mode,
+                    mutability,
+                    mode,
                     name: ident.node,
                     var: id,
                     ty: var_ty,
@@ -470,7 +470,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
         Pattern {
             span: pat.span,
-            ty: ty,
+            ty,
             kind: Box::new(kind),
         }
     }
@@ -569,10 +569,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
                     };
                     PatternKind::Variant {
-                        adt_def: adt_def,
-                        substs: substs,
+                        adt_def,
+                        substs,
                         variant_index: adt_def.variant_index_with_id(variant_id),
-                        subpatterns: subpatterns,
+                        subpatterns,
                     }
                 } else {
                     PatternKind::Leaf { subpatterns: subpatterns }
@@ -626,8 +626,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         };
 
         Pattern {
-            span: span,
-            ty: ty,
+            span,
+            ty,
             kind: Box::new(kind),
         }
     }
@@ -762,7 +762,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         };
 
         Pattern {
-            span: span,
+            span,
             ty: pat_ty,
             kind: Box::new(kind),
         }
diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs
index 719f6b6a7b3..b67048939e4 100644
--- a/src/librustc_const_math/float.rs
+++ b/src/librustc_const_math/float.rs
@@ -37,13 +37,6 @@ impl ConstFloat {
         self.ty.ty_to_string()
     }
 
-    pub fn is_nan(&self) -> bool {
-        match self.ty {
-            ast::FloatTy::F32 => Single::from_bits(self.bits).is_nan(),
-            ast::FloatTy::F64 => Double::from_bits(self.bits).is_nan(),
-        }
-    }
-
     /// Compares the values if they are of the same type
     pub fn try_cmp(self, rhs: Self) -> Result<Ordering, ConstMathErr> {
         match (self.ty, rhs.ty) {
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index 3947edecb5a..93b70ef8e4a 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_const_math"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs
index c03c2890ba3..52306de74cb 100644
--- a/src/librustc_data_structures/accumulate_vec.rs
+++ b/src/librustc_data_structures/accumulate_vec.rs
@@ -13,7 +13,7 @@
 //! Space for up to N elements is provided on the stack.  If more elements are collected, Vec is
 //! used to store the values on the heap.
 //!
-//! The N above is determined by Array's implementor, by way of an associatated constant.
+//! The N above is determined by Array's implementor, by way of an associated constant.
 
 use std::ops::{Deref, DerefMut};
 use std::iter::{self, IntoIterator, FromIterator};
diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs
index df660d08603..1e67461e055 100644
--- a/src/librustc_data_structures/array_vec.rs
+++ b/src/librustc_data_structures/array_vec.rs
@@ -281,8 +281,8 @@ impl<A: Array> IntoIterator for ArrayVec<A> {
         let indices = 0..self.count;
         mem::forget(self);
         Iter {
-            indices: indices,
-            store: store,
+            indices,
+            store,
         }
     }
 }
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index 7fc59be780f..7331016c2d2 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -151,7 +151,7 @@ impl BitMatrix {
         // element. Round up to an even number of u64s.
         let u64s_per_row = u64s(columns);
         BitMatrix {
-            columns: columns,
+            columns,
             vector: vec![0; rows * u64s_per_row],
         }
     }
diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs
index 5adeef1ab3a..6b8bf8df0d3 100644
--- a/src/librustc_data_structures/blake2b.rs
+++ b/src/librustc_data_structures/blake2b.rs
@@ -24,7 +24,7 @@ use std::mem;
 use std::slice;
 
 #[repr(C)]
-pub struct Blake2bCtx {
+struct Blake2bCtx {
     b: [u8; 128],
     h: [u64; 8],
     t: [u64; 2],
diff --git a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
index ab675db2150..90670517f59 100644
--- a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
+++ b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs
@@ -71,8 +71,8 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(graph: &G,
     }
 
     Dominators {
-        post_order_rank: post_order_rank,
-        immediate_dominators: immediate_dominators,
+        post_order_rank,
+        immediate_dominators,
     }
 }
 
@@ -134,56 +134,10 @@ impl<Node: Idx> Dominators<Node> {
         self.dominators(node).any(|n| n == dom)
     }
 
-    pub fn mutual_dominator_node(&self, node1: Node, node2: Node) -> Node {
-        assert!(self.is_reachable(node1),
-                "node {:?} is not reachable",
-                node1);
-        assert!(self.is_reachable(node2),
-                "node {:?} is not reachable",
-                node2);
-        intersect::<Node>(&self.post_order_rank,
-                          &self.immediate_dominators,
-                          node1,
-                          node2)
-    }
-
-    pub fn mutual_dominator<I>(&self, iter: I) -> Option<Node>
-        where I: IntoIterator<Item = Node>
-    {
-        let mut iter = iter.into_iter();
-        iter.next()
-            .map(|dom| iter.fold(dom, |dom, node| self.mutual_dominator_node(dom, node)))
-    }
-
-    pub fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> {
+    #[cfg(test)]
+    fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> {
         &self.immediate_dominators
     }
-
-    pub fn dominator_tree(&self) -> DominatorTree<Node> {
-        let elem: Vec<Node> = Vec::new();
-        let mut children: IndexVec<Node, Vec<Node>> =
-            IndexVec::from_elem_n(elem, self.immediate_dominators.len());
-        let mut root = None;
-        for (index, immed_dom) in self.immediate_dominators.iter().enumerate() {
-            let node = Node::new(index);
-            match *immed_dom {
-                None => {
-                    // node not reachable
-                }
-                Some(immed_dom) => {
-                    if node == immed_dom {
-                        root = Some(node);
-                    } else {
-                        children[immed_dom].push(node);
-                    }
-                }
-            }
-        }
-        DominatorTree {
-            root: root.unwrap(),
-            children: children,
-        }
-    }
 }
 
 pub struct Iter<'dom, Node: Idx + 'dom> {
@@ -215,38 +169,9 @@ pub struct DominatorTree<N: Idx> {
 }
 
 impl<Node: Idx> DominatorTree<Node> {
-    pub fn root(&self) -> Node {
-        self.root
-    }
-
     pub fn children(&self, node: Node) -> &[Node] {
         &self.children[node]
     }
-
-    pub fn iter_children_of(&self, node: Node) -> IterChildrenOf<Node> {
-        IterChildrenOf {
-            tree: self,
-            stack: vec![node],
-        }
-    }
-}
-
-pub struct IterChildrenOf<'iter, Node: Idx + 'iter> {
-    tree: &'iter DominatorTree<Node>,
-    stack: Vec<Node>,
-}
-
-impl<'iter, Node: Idx> Iterator for IterChildrenOf<'iter, Node> {
-    type Item = Node;
-
-    fn next(&mut self) -> Option<Node> {
-        if let Some(node) = self.stack.pop() {
-            self.stack.extend(self.tree.children(node));
-            Some(node)
-        } else {
-            None
-        }
-    }
 }
 
 impl<Node: Idx> fmt::Debug for DominatorTree<Node> {
diff --git a/src/librustc_data_structures/control_flow_graph/iterate/mod.rs b/src/librustc_data_structures/control_flow_graph/iterate/mod.rs
index 11b557cbcad..2d70b406342 100644
--- a/src/librustc_data_structures/control_flow_graph/iterate/mod.rs
+++ b/src/librustc_data_structures/control_flow_graph/iterate/mod.rs
@@ -47,22 +47,6 @@ fn post_order_walk<G: ControlFlowGraph>(graph: &G,
     result.push(node);
 }
 
-pub fn pre_order_walk<G: ControlFlowGraph>(graph: &G,
-                                           node: G::Node,
-                                           result: &mut Vec<G::Node>,
-                                           visited: &mut IndexVec<G::Node, bool>) {
-    if visited[node] {
-        return;
-    }
-    visited[node] = true;
-
-    result.push(node);
-
-    for successor in graph.successors(node) {
-        pre_order_walk(graph, successor, result, visited);
-    }
-}
-
 pub fn reverse_post_order<G: ControlFlowGraph>(graph: &G, start_node: G::Node) -> Vec<G::Node> {
     let mut vec = post_order_from(graph, start_node);
     vec.reverse();
diff --git a/src/librustc_data_structures/control_flow_graph/iterate/test.rs b/src/librustc_data_structures/control_flow_graph/iterate/test.rs
index dca45602f17..100881ddfdd 100644
--- a/src/librustc_data_structures/control_flow_graph/iterate/test.rs
+++ b/src/librustc_data_structures/control_flow_graph/iterate/test.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use super::super::test::TestGraph;
-use super::super::transpose::TransposedGraph;
 
 use super::*;
 
@@ -20,22 +19,3 @@ fn diamond_post_order() {
     let result = post_order_from(&graph, 0);
     assert_eq!(result, vec![3, 1, 2, 0]);
 }
-
-
-#[test]
-fn rev_post_order_inner_loop() {
-    // 0 -> 1 ->     2     -> 3 -> 5
-    //      ^     ^    v      |
-    //      |     6 <- 4      |
-    //      +-----------------+
-    let graph = TestGraph::new(0,
-                               &[(0, 1), (1, 2), (2, 3), (3, 5), (3, 1), (2, 4), (4, 6), (6, 2)]);
-
-    let rev_graph = TransposedGraph::new(&graph);
-
-    let result = post_order_from_to(&rev_graph, 6, Some(2));
-    assert_eq!(result, vec![4, 6]);
-
-    let result = post_order_from_to(&rev_graph, 3, Some(1));
-    assert_eq!(result, vec![4, 6, 2, 3]);
-}
diff --git a/src/librustc_data_structures/control_flow_graph/mod.rs b/src/librustc_data_structures/control_flow_graph/mod.rs
index eb6839df627..7bf776675c6 100644
--- a/src/librustc_data_structures/control_flow_graph/mod.rs
+++ b/src/librustc_data_structures/control_flow_graph/mod.rs
@@ -9,13 +9,10 @@
 // except according to those terms.
 
 use super::indexed_vec::Idx;
-pub use std::slice::Iter;
 
 pub mod dominators;
 pub mod iterate;
-pub mod reachable;
 mod reference;
-pub mod transpose;
 
 #[cfg(test)]
 mod test;
diff --git a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs b/src/librustc_data_structures/control_flow_graph/reachable/mod.rs
deleted file mode 100644
index 24210ebb95d..00000000000
--- a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Compute reachability using a simple dataflow propagation.
-//! Store end-result in a big NxN bit matrix.
-
-use super::ControlFlowGraph;
-use super::super::bitvec::BitVector;
-use super::iterate::reverse_post_order;
-use super::super::indexed_vec::{IndexVec, Idx};
-
-#[cfg(test)]
-mod test;
-
-pub fn reachable<G: ControlFlowGraph>(graph: &G) -> Reachability<G::Node> {
-    let reverse_post_order = reverse_post_order(graph, graph.start_node());
-    reachable_given_rpo(graph, &reverse_post_order)
-}
-
-pub fn reachable_given_rpo<G: ControlFlowGraph>(graph: &G,
-                                                reverse_post_order: &[G::Node])
-                                                -> Reachability<G::Node> {
-    let mut reachability = Reachability::new(graph);
-    let mut changed = true;
-    while changed {
-        changed = false;
-        for &node in reverse_post_order.iter().rev() {
-            // every node can reach itself
-            changed |= reachability.bits[node].insert(node.index());
-
-            // and every pred can reach everything node can reach
-            for pred in graph.predecessors(node) {
-                let nodes_bits = reachability.bits[node].clone();
-                changed |= reachability.bits[pred].insert_all(&nodes_bits);
-            }
-        }
-    }
-    reachability
-}
-
-pub struct Reachability<Node: Idx> {
-    bits: IndexVec<Node, BitVector>,
-}
-
-impl<Node: Idx> Reachability<Node> {
-    fn new<G: ControlFlowGraph>(graph: &G) -> Self {
-        let num_nodes = graph.num_nodes();
-        Reachability { bits: IndexVec::from_elem_n(BitVector::new(num_nodes), num_nodes) }
-    }
-
-    pub fn can_reach(&self, source: Node, target: Node) -> bool {
-        let bit: usize = target.index();
-        self.bits[source].contains(bit)
-    }
-}
diff --git a/src/librustc_data_structures/control_flow_graph/reachable/test.rs b/src/librustc_data_structures/control_flow_graph/reachable/test.rs
deleted file mode 100644
index ef45deeaafc..00000000000
--- a/src/librustc_data_structures/control_flow_graph/reachable/test.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use super::super::test::TestGraph;
-
-use super::*;
-
-#[test]
-fn test1() {
-    // 0 -> 1 -> 2 -> 3
-    //      ^    v
-    //      6 <- 4 -> 5
-    let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (2, 4), (4, 5), (4, 6), (6, 1)]);
-    let reachable = reachable(&graph);
-    assert!((0..6).all(|i| reachable.can_reach(0, i)));
-    assert!((1..6).all(|i| reachable.can_reach(1, i)));
-    assert!((1..6).all(|i| reachable.can_reach(2, i)));
-    assert!((1..6).all(|i| reachable.can_reach(4, i)));
-    assert!((1..6).all(|i| reachable.can_reach(6, i)));
-    assert!(reachable.can_reach(3, 3));
-    assert!(!reachable.can_reach(3, 5));
-    assert!(!reachable.can_reach(5, 3));
-}
-
-/// use bigger indices to cross between words in the bit set
-#[test]
-fn test2() {
-    // 30 -> 31 -> 32 -> 33
-    //       ^      v
-    //       36 <- 34 -> 35
-    let graph = TestGraph::new(30,
-                               &[(30, 31), (31, 32), (32, 33), (32, 34), (34, 35), (34, 36),
-                                 (36, 31)]);
-    let reachable = reachable(&graph);
-    assert!((30..36).all(|i| reachable.can_reach(30, i)));
-    assert!((31..36).all(|i| reachable.can_reach(31, i)));
-    assert!((31..36).all(|i| reachable.can_reach(32, i)));
-    assert!((31..36).all(|i| reachable.can_reach(34, i)));
-    assert!((31..36).all(|i| reachable.can_reach(36, i)));
-    assert!(reachable.can_reach(33, 33));
-    assert!(!reachable.can_reach(33, 35));
-    assert!(!reachable.can_reach(35, 33));
-}
diff --git a/src/librustc_data_structures/control_flow_graph/test.rs b/src/librustc_data_structures/control_flow_graph/test.rs
index d48a6e684ad..f04b536bc18 100644
--- a/src/librustc_data_structures/control_flow_graph/test.rs
+++ b/src/librustc_data_structures/control_flow_graph/test.rs
@@ -26,7 +26,7 @@ impl TestGraph {
     pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self {
         let mut graph = TestGraph {
             num_nodes: start_node + 1,
-            start_node: start_node,
+            start_node,
             successors: HashMap::new(),
             predecessors: HashMap::new(),
         };
diff --git a/src/librustc_data_structures/control_flow_graph/transpose.rs b/src/librustc_data_structures/control_flow_graph/transpose.rs
deleted file mode 100644
index a1a117edb94..00000000000
--- a/src/librustc_data_structures/control_flow_graph/transpose.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use super::*;
-
-pub struct TransposedGraph<G: ControlFlowGraph> {
-    base_graph: G,
-    start_node: G::Node,
-}
-
-impl<G: ControlFlowGraph> TransposedGraph<G> {
-    pub fn new(base_graph: G) -> Self {
-        let start_node = base_graph.start_node();
-        Self::with_start(base_graph, start_node)
-    }
-
-    pub fn with_start(base_graph: G, start_node: G::Node) -> Self {
-        TransposedGraph {
-            base_graph: base_graph,
-            start_node: start_node,
-        }
-    }
-}
-
-impl<G: ControlFlowGraph> ControlFlowGraph for TransposedGraph<G> {
-    type Node = G::Node;
-
-    fn num_nodes(&self) -> usize {
-        self.base_graph.num_nodes()
-    }
-
-    fn start_node(&self) -> Self::Node {
-        self.start_node
-    }
-
-    fn predecessors<'graph>(&'graph self,
-                            node: Self::Node)
-                            -> <Self as GraphPredecessors<'graph>>::Iter {
-        self.base_graph.successors(node)
-    }
-
-    fn successors<'graph>(&'graph self,
-                          node: Self::Node)
-                          -> <Self as GraphSuccessors<'graph>>::Iter {
-        self.base_graph.predecessors(node)
-    }
-}
-
-impl<'graph, G: ControlFlowGraph> GraphPredecessors<'graph> for TransposedGraph<G> {
-    type Item = G::Node;
-    type Iter = <G as GraphSuccessors<'graph>>::Iter;
-}
-
-impl<'graph, G: ControlFlowGraph> GraphSuccessors<'graph> for TransposedGraph<G> {
-    type Item = G::Node;
-    type Iter = <G as GraphPredecessors<'graph>>::Iter;
-}
diff --git a/src/librustc_data_structures/fmt_wrap.rs b/src/librustc_data_structures/fmt_wrap.rs
deleted file mode 100644
index 50fd1d802b7..00000000000
--- a/src/librustc_data_structures/fmt_wrap.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::fmt;
-
-// Provide some more formatting options for some data types (at the moment
-// that's just `{:x}` for slices of u8).
-
-pub struct FmtWrap<T>(pub T);
-
-impl<'a> fmt::LowerHex for FmtWrap<&'a [u8]> {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        for byte in self.0.iter() {
-            try!(write!(formatter, "{:02x}", byte));
-        }
-        Ok(())
-    }
-}
-
-#[test]
-fn test_lower_hex() {
-    let bytes: &[u8] = &[0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
-    assert_eq!("0123456789abcdef", &format!("{:x}", FmtWrap(bytes)));
-}
diff --git a/src/librustc_data_structures/fx.rs b/src/librustc_data_structures/fx.rs
index 00dfc1617a8..5bf25437763 100644
--- a/src/librustc_data_structures/fx.rs
+++ b/src/librustc_data_structures/fx.rs
@@ -107,9 +107,3 @@ impl Hasher for FxHasher {
         self.hash as u64
     }
 }
-
-pub fn hash<T: Hash>(v: &T) -> u64 {
-    let mut state = FxHasher::default();
-    v.hash(&mut state);
-    state.finish()
-}
diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs
index f562ae0e3b8..a5f83ce05f5 100644
--- a/src/librustc_data_structures/graph/mod.rs
+++ b/src/librustc_data_structures/graph/mod.rs
@@ -106,13 +106,6 @@ impl NodeIndex {
     }
 }
 
-impl EdgeIndex {
-    /// Returns unique id (unique with respect to the graph holding associated edge).
-    pub fn edge_id(&self) -> usize {
-        self.0
-    }
-}
-
 impl<N: Debug, E: Debug> Graph<N, E> {
     pub fn new() -> Graph<N, E> {
         Graph {
@@ -153,7 +146,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         let idx = self.next_node_index();
         self.nodes.push(Node {
             first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
-            data: data,
+            data,
         });
         idx
     }
@@ -189,9 +182,9 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         // as the next pointers
         self.edges.push(Edge {
             next_edge: [source_first, target_first],
-            source: source,
-            target: target,
-            data: data,
+            source,
+            target,
+            data,
         });
 
         // adjust the firsts for each node target be the next object.
@@ -201,34 +194,10 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         return idx;
     }
 
-    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
-        &mut self.edges[idx.0].data
-    }
-
-    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
-        &self.edges[idx.0].data
-    }
-
     pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
         &self.edges[idx.0]
     }
 
-    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
-        //! Accesses the index of the first edge adjacent to `node`.
-        //! This is useful if you wish to modify the graph while walking
-        //! the linked list of edges.
-
-        self.nodes[node.0].first_edge[dir.repr]
-    }
-
-    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
-        //! Accesses the next edge in a given direction.
-        //! This is useful if you wish to modify the graph while walking
-        //! the linked list of edges.
-
-        self.edges[edge.0].next_edge[dir.repr]
-    }
-
     // # Iterating over nodes, edges
 
     pub fn enumerated_nodes(&self) -> EnumeratedNodes<N> {
@@ -269,7 +238,7 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         let first_edge = self.node(source).first_edge[direction.repr];
         AdjacentEdges {
             graph: self,
-            direction: direction,
+            direction,
             next: first_edge,
         }
     }
@@ -282,25 +251,6 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         self.incoming_edges(target).sources()
     }
 
-    /// A common use for graphs in our compiler is to perform
-    /// fixed-point iteration. In this case, each edge represents a
-    /// constraint, and the nodes themselves are associated with
-    /// variables or other bitsets. This method facilitates such a
-    /// computation.
-    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
-        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
-    {
-        let mut iteration = 0;
-        let mut changed = true;
-        while changed {
-            changed = false;
-            iteration += 1;
-            for (edge_index, edge) in self.enumerated_edges() {
-                changed |= op(iteration, edge_index, edge);
-            }
-        }
-    }
-
     pub fn depth_traverse<'a>(&'a self,
                               start: NodeIndex,
                               direction: Direction)
@@ -343,35 +293,6 @@ impl<N: Debug, E: Debug> Graph<N, E> {
         assert_eq!(result.len(), self.len_nodes());
         result
     }
-
-    /// Whether or not a node can be reached from itself.
-    pub fn is_node_cyclic(&self, starting_node_index: NodeIndex) -> bool {
-        // This is similar to depth traversal below, but we
-        // can't use that, because depth traversal doesn't show
-        // the starting node a second time.
-        let mut visited = BitVector::new(self.len_nodes());
-        let mut stack = vec![starting_node_index];
-
-        while let Some(current_node_index) = stack.pop() {
-            visited.insert(current_node_index.0);
-
-            // Directionality doesn't change the answer,
-            // so just use outgoing edges.
-            for (_, edge) in self.outgoing_edges(current_node_index) {
-                let target_node_index = edge.target();
-
-                if target_node_index == starting_node_index {
-                    return true;
-                }
-
-                if !visited.contains(target_node_index.0) {
-                    stack.push(target_node_index);
-                }
-            }
-        }
-
-        false
-    }
 }
 
 // # Iterators
@@ -479,16 +400,6 @@ pub struct DepthFirstTraversal<'g, N, E>
 }
 
 impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
-    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
-        let visited = BitVector::new(graph.len_nodes());
-        DepthFirstTraversal {
-            graph: graph,
-            stack: vec![],
-            visited: visited,
-            direction: direction,
-        }
-    }
-
     pub fn with_start_node(graph: &'g Graph<N, E>,
                            start_node: NodeIndex,
                            direction: Direction)
@@ -496,20 +407,13 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
         let mut visited = BitVector::new(graph.len_nodes());
         visited.insert(start_node.node_id());
         DepthFirstTraversal {
-            graph: graph,
+            graph,
             stack: vec![start_node],
-            visited: visited,
-            direction: direction,
+            visited,
+            direction,
         }
     }
 
-    pub fn reset(&mut self, start_node: NodeIndex) {
-        self.stack.truncate(0);
-        self.stack.push(start_node);
-        self.visited.clear();
-        self.visited.insert(start_node.node_id());
-    }
-
     fn visit(&mut self, node: NodeIndex) {
         if self.visited.insert(node.node_id()) {
             self.stack.push(node);
@@ -532,19 +436,6 @@ impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
     }
 }
 
-pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
-    where F: FnMut(EdgeIndex) -> bool
-{
-    let mut i = 0;
-    let n = max_edge_index.0;
-    while i < n {
-        if !f(EdgeIndex(i)) {
-            return;
-        }
-        i += 1;
-    }
-}
-
 impl<E> Edge<E> {
     pub fn source(&self) -> NodeIndex {
         self.source
diff --git a/src/librustc_data_structures/graph/tests.rs b/src/librustc_data_structures/graph/tests.rs
index b6a0d4cff5a..007704357af 100644
--- a/src/librustc_data_structures/graph/tests.rs
+++ b/src/librustc_data_structures/graph/tests.rs
@@ -43,29 +43,6 @@ fn create_graph() -> TestGraph {
     return graph;
 }
 
-fn create_graph_with_cycle() -> TestGraph {
-    let mut graph = Graph::new();
-
-    // Create a graph with a cycle.
-    //
-    //    A --> B <-- +
-    //          |     |
-    //          v     |
-    //          C --> D
-
-    let a = graph.add_node("A");
-    let b = graph.add_node("B");
-    let c = graph.add_node("C");
-    let d = graph.add_node("D");
-
-    graph.add_edge(a, b, "AB");
-    graph.add_edge(b, c, "BC");
-    graph.add_edge(c, d, "CD");
-    graph.add_edge(d, b, "DB");
-
-    return graph;
-}
-
 #[test]
 fn each_node() {
     let graph = create_graph();
@@ -82,7 +59,6 @@ fn each_edge() {
     let graph = create_graph();
     let expected = ["AB", "BC", "BD", "DE", "EC", "FB"];
     graph.each_edge(|idx, edge| {
-        assert_eq!(&expected[idx.0], graph.edge_data(idx));
         assert_eq!(expected[idx.0], edge.data);
         true
     });
@@ -97,7 +73,6 @@ fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(graph: &Graph
 
     let mut counter = 0;
     for (edge_index, edge) in graph.incoming_edges(start_index) {
-        assert!(graph.edge_data(edge_index) == &edge.data);
         assert!(counter < expected_incoming.len());
         debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                counter,
@@ -117,7 +92,6 @@ fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(graph: &Graph
 
     let mut counter = 0;
     for (edge_index, edge) in graph.outgoing_edges(start_index) {
-        assert!(graph.edge_data(edge_index) == &edge.data);
         assert!(counter < expected_outgoing.len());
         debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                counter,
@@ -163,58 +137,3 @@ fn each_adjacent_from_d() {
     let graph = create_graph();
     test_adjacent_edges(&graph, NodeIndex(3), "D", &[("BD", "B")], &[("DE", "E")]);
 }
-
-#[test]
-fn is_node_cyclic_a() {
-    let graph = create_graph_with_cycle();
-    assert!(!graph.is_node_cyclic(NodeIndex(0)));
-}
-
-#[test]
-fn is_node_cyclic_b() {
-    let graph = create_graph_with_cycle();
-    assert!(graph.is_node_cyclic(NodeIndex(1)));
-}
-
-#[test]
-fn nodes_in_postorder() {
-    let expected = vec![
-        ("A", vec!["C", "E", "D", "B", "A", "F"]),
-        ("B", vec!["C", "E", "D", "B", "A", "F"]),
-        ("C", vec!["C", "E", "D", "B", "A", "F"]),
-        ("D", vec!["C", "E", "D", "B", "A", "F"]),
-        ("E", vec!["C", "E", "D", "B", "A", "F"]),
-        ("F", vec!["C", "E", "D", "B", "F", "A"])
-    ];
-
-    let graph = create_graph();
-
-    for ((idx, node), &(node_name, ref expected))
-        in graph.enumerated_nodes().zip(&expected)
-    {
-        assert_eq!(node.data, node_name);
-        assert_eq!(expected,
-                   &graph.nodes_in_postorder(OUTGOING, idx)
-                   .into_iter().map(|idx| *graph.node_data(idx))
-                   .collect::<Vec<&str>>());
-    }
-
-    let expected = vec![
-        ("A", vec!["D", "C", "B", "A"]),
-        ("B", vec!["D", "C", "B", "A"]),
-        ("C", vec!["B", "D", "C", "A"]),
-        ("D", vec!["C", "B", "D", "A"]),
-    ];
-
-    let graph = create_graph_with_cycle();
-
-    for ((idx, node), &(node_name, ref expected))
-        in graph.enumerated_nodes().zip(&expected)
-    {
-        assert_eq!(node.data, node_name);
-        assert_eq!(expected,
-                   &graph.nodes_in_postorder(OUTGOING, idx)
-                   .into_iter().map(|idx| *graph.node_data(idx))
-                   .collect::<Vec<&str>>());
-    }
-}
diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs
index 572ce98d3ae..9cb6806e9ad 100644
--- a/src/librustc_data_structures/indexed_set.rs
+++ b/src/librustc_data_structures/indexed_set.rs
@@ -153,4 +153,68 @@ impl<T: Idx> IdxSet<T> {
     pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
         bitwise(self.words_mut(), other.words(), &Subtract)
     }
+
+    /// Calls `f` on each index value held in this set, up to the
+    /// bound `max_bits` on the size of universe of indexes.
+    pub fn each_bit<F>(&self, max_bits: usize, f: F) where F: FnMut(T) {
+        each_bit(self, max_bits, f)
+    }
+
+    /// Removes all elements from this set.
+    pub fn reset_to_empty(&mut self) {
+        for word in self.words_mut() { *word = 0; }
+    }
+
+    pub fn elems(&self, universe_size: usize) -> Elems<T> {
+        Elems { i: 0, set: self, universe_size: universe_size }
+    }
+}
+
+pub struct Elems<'a, T: Idx> { i: usize, set: &'a IdxSet<T>, universe_size: usize }
+
+impl<'a, T: Idx> Iterator for Elems<'a, T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        if self.i >= self.universe_size { return None; }
+        let mut i = self.i;
+        loop {
+            if i >= self.universe_size {
+                self.i = i; // (mark iteration as complete.)
+                return None;
+            }
+            if self.set.contains(&T::new(i)) {
+                self.i = i + 1; // (next element to start at.)
+                return Some(T::new(i));
+            }
+            i = i + 1;
+        }
+    }
+}
+
+fn each_bit<T: Idx, F>(words: &IdxSet<T>, max_bits: usize, mut f: F) where F: FnMut(T) {
+    let usize_bits: usize = mem::size_of::<usize>() * 8;
+
+    for (word_index, &word) in words.words().iter().enumerate() {
+        if word != 0 {
+            let base_index = word_index * usize_bits;
+            for offset in 0..usize_bits {
+                let bit = 1 << offset;
+                if (word & bit) != 0 {
+                    // NB: we round up the total number of bits
+                    // that we store in any given bit set so that
+                    // it is an even multiple of usize::BITS. This
+                    // means that there may be some stray bits at
+                    // the end that do not correspond to any
+                    // actual value; that's why we first check
+                    // that we are in range of bits_per_block.
+                    let bit_index = base_index + offset as usize;
+                    if bit_index >= max_bits {
+                        return;
+                    } else {
+                        f(Idx::new(bit_index));
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/src/librustc_data_structures/ivar.rs b/src/librustc_data_structures/ivar.rs
deleted file mode 100644
index f842f4a41a1..00000000000
--- a/src/librustc_data_structures/ivar.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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.
-
-use std::fmt;
-use std::cell::Cell;
-
-/// A write-once variable. When constructed, it is empty, and
-/// can only be set once.
-///
-/// Ivars ensure that data that can only be initialised once. A full
-/// implementation is used for concurrency and blocks on a read of an
-/// unfulfilled value. This implementation is more minimal and panics
-/// if you attempt to read the value before it has been set. It is also
-/// not `Sync`, but may be extended in the future to be usable as a true
-/// concurrency type.
-///
-/// The `T: Copy` bound is not strictly needed, but it is required by
-/// Cell (so removing it would require using UnsafeCell), and it
-/// suffices for the current purposes.
-#[derive(PartialEq)]
-pub struct Ivar<T: Copy> {
-    data: Cell<Option<T>>,
-}
-
-impl<T: Copy> Ivar<T> {
-    pub fn new() -> Ivar<T> {
-        Ivar { data: Cell::new(None) }
-    }
-
-    pub fn get(&self) -> Option<T> {
-        self.data.get()
-    }
-
-    pub fn fulfill(&self, value: T) {
-        assert!(self.data.get().is_none(), "Value already set!");
-        self.data.set(Some(value));
-    }
-
-    pub fn is_fulfilled(&self) -> bool {
-        self.data.get().is_some()
-    }
-
-    pub fn unwrap(&self) -> T {
-        self.get().unwrap()
-    }
-}
-
-impl<T: Copy + fmt::Debug> fmt::Debug for Ivar<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.get() {
-            Some(val) => write!(f, "Ivar({:?})", val),
-            None => f.write_str("Ivar(<unfulfilled>)"),
-        }
-    }
-}
-
-impl<T: Copy> Clone for Ivar<T> {
-    fn clone(&self) -> Ivar<T> {
-        match self.get() {
-            Some(val) => Ivar { data: Cell::new(Some(val)) },
-            None => Ivar::new(),
-        }
-    }
-}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 3cb3e088364..da00ebc4b9e 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -16,9 +16,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_data_structures"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -52,11 +49,9 @@ pub mod accumulate_vec;
 pub mod small_vec;
 pub mod base_n;
 pub mod bitslice;
-pub mod blake2b;
 pub mod bitvec;
-pub mod fmt_wrap;
+pub mod blake2b;
 pub mod graph;
-pub mod ivar;
 pub mod indexed_set;
 pub mod indexed_vec;
 pub mod obligation_forest;
diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 6e70944ce64..02cae52166a 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -57,11 +57,6 @@ pub trait ObligationProcessor {
         where I: Clone + Iterator<Item=&'c Self::Obligation>;
 }
 
-struct SnapshotData {
-    node_len: usize,
-    cache_list_len: usize,
-}
-
 pub struct ObligationForest<O: ForestObligation> {
     /// The list of obligations. In between calls to
     /// `process_obligations`, this list only contains nodes in the
@@ -83,14 +78,9 @@ pub struct ObligationForest<O: ForestObligation> {
     /// A list of the obligations added in snapshots, to allow
     /// for their removal.
     cache_list: Vec<O::Predicate>,
-    snapshots: Vec<SnapshotData>,
     scratch: Option<Vec<usize>>,
 }
 
-pub struct Snapshot {
-    len: usize,
-}
-
 #[derive(Debug)]
 struct Node<O> {
     obligation: O,
@@ -166,7 +156,6 @@ impl<O: ForestObligation> ObligationForest<O> {
     pub fn new() -> ObligationForest<O> {
         ObligationForest {
             nodes: vec![],
-            snapshots: vec![],
             done_cache: FxHashSet(),
             waiting_cache: FxHashMap(),
             cache_list: vec![],
@@ -180,39 +169,6 @@ impl<O: ForestObligation> ObligationForest<O> {
         self.nodes.len()
     }
 
-    pub fn start_snapshot(&mut self) -> Snapshot {
-        self.snapshots.push(SnapshotData {
-            node_len: self.nodes.len(),
-            cache_list_len: self.cache_list.len()
-        });
-        Snapshot { len: self.snapshots.len() }
-    }
-
-    pub fn commit_snapshot(&mut self, snapshot: Snapshot) {
-        assert_eq!(snapshot.len, self.snapshots.len());
-        let info = self.snapshots.pop().unwrap();
-        assert!(self.nodes.len() >= info.node_len);
-        assert!(self.cache_list.len() >= info.cache_list_len);
-    }
-
-    pub fn rollback_snapshot(&mut self, snapshot: Snapshot) {
-        // Check that we are obeying stack discipline.
-        assert_eq!(snapshot.len, self.snapshots.len());
-        let info = self.snapshots.pop().unwrap();
-
-        for entry in &self.cache_list[info.cache_list_len..] {
-            self.done_cache.remove(entry);
-            self.waiting_cache.remove(entry);
-        }
-
-        self.nodes.truncate(info.node_len);
-        self.cache_list.truncate(info.cache_list_len);
-    }
-
-    pub fn in_snapshot(&self) -> bool {
-        !self.snapshots.is_empty()
-    }
-
     /// Registers an obligation
     ///
     /// This CAN be done in a snapshot
@@ -262,14 +218,13 @@ impl<O: ForestObligation> ObligationForest<O> {
     ///
     /// This cannot be done during a snapshot.
     pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
-        assert!(!self.in_snapshot());
         let mut errors = vec![];
         for index in 0..self.nodes.len() {
             if let NodeState::Pending = self.nodes[index].state.get() {
                 let backtrace = self.error_at(index);
                 errors.push(Error {
                     error: error.clone(),
-                    backtrace: backtrace,
+                    backtrace,
                 });
             }
         }
@@ -297,7 +252,6 @@ impl<O: ForestObligation> ObligationForest<O> {
         where P: ObligationProcessor<Obligation=O>
     {
         debug!("process_obligations(len={})", self.nodes.len());
-        assert!(!self.in_snapshot()); // cannot unroll this action
 
         let mut errors = vec![];
         let mut stalled = true;
@@ -346,7 +300,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                     let backtrace = self.error_at(index);
                     errors.push(Error {
                         error: err,
-                        backtrace: backtrace,
+                        backtrace,
                     });
                 }
             }
@@ -357,8 +311,8 @@ impl<O: ForestObligation> ObligationForest<O> {
             // changed.
             return Outcome {
                 completed: vec![],
-                errors: errors,
-                stalled: stalled,
+                errors,
+                stalled,
             };
         }
 
@@ -372,8 +326,8 @@ impl<O: ForestObligation> ObligationForest<O> {
 
         Outcome {
             completed: completed_obligations,
-            errors: errors,
-            stalled: stalled,
+            errors,
+            stalled,
         }
     }
 
@@ -528,8 +482,6 @@ impl<O: ForestObligation> ObligationForest<O> {
     /// on these nodes may be present. This is done by e.g. `process_cycles`.
     #[inline(never)]
     fn compress(&mut self) -> Vec<O> {
-        assert!(!self.in_snapshot()); // didn't write code to unroll this action
-
         let nodes_len = self.nodes.len();
         let mut node_rewrites: Vec<_> = self.scratch.take().unwrap();
         node_rewrites.extend(0..nodes_len);
@@ -638,8 +590,8 @@ impl<O: ForestObligation> ObligationForest<O> {
 impl<O> Node<O> {
     fn new(parent: Option<NodeIndex>, obligation: O) -> Node<O> {
         Node {
-            obligation: obligation,
-            parent: parent,
+            obligation,
+            parent,
             state: Cell::new(NodeState::Pending),
             dependents: vec![],
         }
diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs
index 4e2b3786021..74738e61b44 100644
--- a/src/librustc_data_structures/small_vec.rs
+++ b/src/librustc_data_structures/small_vec.rs
@@ -14,7 +14,7 @@
 //! used to store the values on the heap. SmallVec is similar to AccumulateVec, but adds
 //! the ability to push elements.
 //!
-//! The N above is determined by Array's implementor, by way of an associatated constant.
+//! The N above is determined by Array's implementor, by way of an associated constant.
 
 use std::ops::{Deref, DerefMut};
 use std::iter::{IntoIterator, FromIterator};
diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs
index e2d3a4f4537..7853bf9478a 100644
--- a/src/librustc_data_structures/unify/mod.rs
+++ b/src/librustc_data_structures/unify/mod.rs
@@ -87,8 +87,8 @@ impl<K: UnifyKey> VarValue<K> {
     fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> {
         VarValue {
             parent: parent, // this is a root
-            value: value,
-            rank: rank,
+            value,
+            rank,
         }
     }
 
@@ -98,8 +98,8 @@ impl<K: UnifyKey> VarValue<K> {
 
     fn root(self, rank: u32, value: K::Value) -> VarValue<K> {
         VarValue {
-            rank: rank,
-            value: value,
+            rank,
+            value,
             ..self
         }
     }
@@ -275,7 +275,8 @@ impl<'tcx, K: UnifyKey> UnificationTable<K>
         self.get(id).value
     }
 
-    pub fn unioned(&mut self, a_id: K, b_id: K) -> bool {
+    #[cfg(test)]
+    fn unioned(&mut self, a_id: K, b_id: K) -> bool {
         self.find(a_id) == self.find(b_id)
     }
 }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 1444dcf4271..96688c6ac9c 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -64,6 +64,8 @@ use arena::DroplessArena;
 
 use derive_registrar;
 
+use profile;
+
 pub fn compile_input(sess: &Session,
                      cstore: &CStore,
                      input: &Input,
@@ -105,6 +107,10 @@ pub fn compile_input(sess: &Session,
         sess.abort_if_errors();
     }
 
+    if sess.profile_queries() {
+        profile::begin();
+    }
+
     // 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
@@ -306,7 +312,7 @@ pub fn source_name(input: &Input) -> String {
     }
 }
 
-/// CompileController is used to customise compilation, it allows compilation to
+/// CompileController is used to customize compilation, it allows compilation to
 /// be stopped and/or to call arbitrary code at various points in compilation.
 /// It also allows for various flags to be set to influence what information gets
 /// collected during compilation.
@@ -401,8 +407,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
              out_dir: &'a Option<PathBuf>)
              -> Self {
         CompileState {
-            input: input,
-            session: session,
+            input,
+            session,
             out_dir: out_dir.as_ref().map(|s| &**s),
             out_file: None,
             arena: None,
@@ -537,6 +543,10 @@ pub fn phase_1_parse_input<'a>(control: &CompileController,
                                -> PResult<'a, ast::Crate> {
     sess.diagnostic().set_continue_after_error(control.continue_parse_after_error);
 
+    if sess.profile_queries() {
+        profile::begin();
+    }
+
     let krate = time(sess.time_passes(), "parsing", || {
         match *input {
             Input::File(ref file) => {
@@ -833,10 +843,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         })
     })?;
 
-    time(time_passes,
-         "early lint checks",
-         || lint::check_ast_crate(sess, &krate));
-
     // Lower ast -> hir.
     let hir_forest = time(time_passes, "lowering ast -> hir", || {
         let hir_crate = lower_crate(sess, &krate, &mut resolver);
@@ -848,6 +854,10 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         hir_map::Forest::new(hir_crate, &sess.dep_graph)
     });
 
+    time(time_passes,
+         "early lint checks",
+         || lint::check_ast_crate(sess, &krate));
+
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !keep_hygiene_data(sess) {
         syntax::ext::hygiene::clear_markings();
@@ -867,8 +877,9 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
             export_map: resolver.export_map,
             trait_map: resolver.trait_map,
             maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
         },
-        hir_forest: hir_forest,
+        hir_forest,
     })
 }
 
@@ -970,7 +981,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED.
 
     // 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"));
@@ -1066,6 +1082,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "borrow checking",
              || borrowck::check_crate(tcx));
 
+        time(time_passes,
+             "MIR borrow checking",
+             || for def_id in tcx.body_owners() { tcx.mir_borrowck(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
@@ -1111,6 +1131,10 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
              "translation",
              move || trans::trans_crate(tcx, analysis, incremental_hashes_map, output_filenames));
 
+    if tcx.sess.profile_queries() {
+        profile::dump("profile_queries".to_string())
+    }
+
     translation
 }
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index f8cd2280caf..1915a1c8648 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -14,16 +14,13 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_driver"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(set_stdio)]
@@ -32,6 +29,7 @@ extern crate arena;
 extern crate getopts;
 extern crate graphviz;
 extern crate env_logger;
+#[cfg(unix)]
 extern crate libc;
 extern crate rustc;
 extern crate rustc_allocator;
@@ -102,8 +100,9 @@ use syntax::parse::{self, PResult};
 use syntax_pos::{DUMMY_SP, MultiSpan};
 
 #[cfg(test)]
-pub mod test;
+mod test;
 
+pub mod profile;
 pub mod driver;
 pub mod pretty;
 pub mod target_features;
@@ -802,7 +801,7 @@ impl RustcDefaultCalls {
                     let mut cfgs = Vec::new();
                     for &(name, ref value) in sess.parse_sess.config.iter() {
                         let gated_cfg = GatedCfg::gate(&ast::MetaItem {
-                            name: name,
+                            name,
                             node: ast::MetaItemKind::Word,
                             span: DUMMY_SP,
                         });
@@ -859,17 +858,17 @@ impl RustcDefaultCalls {
 }
 
 /// Returns a version string such as "0.12.0-dev".
-pub fn release_str() -> Option<&'static str> {
+fn release_str() -> Option<&'static str> {
     option_env!("CFG_RELEASE")
 }
 
 /// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
-pub fn commit_hash_str() -> Option<&'static str> {
+fn commit_hash_str() -> Option<&'static str> {
     option_env!("CFG_VER_HASH")
 }
 
 /// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
-pub fn commit_date_str() -> Option<&'static str> {
+fn commit_date_str() -> Option<&'static str> {
     option_env!("CFG_VER_DATE")
 }
 
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 84d3ab65b1c..20f2a146b0b 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -174,7 +174,7 @@ impl PpSourceMode {
         match *self {
             PpmNormal | PpmEveryBodyLoops | PpmExpanded => {
                 let annotation = NoAnn {
-                    sess: sess,
+                    sess,
                     hir_map: hir_map.map(|m| m.clone()),
                 };
                 f(&annotation)
@@ -182,14 +182,14 @@ impl PpSourceMode {
 
             PpmIdentified | PpmExpandedIdentified => {
                 let annotation = IdentifiedAnnotation {
-                    sess: sess,
+                    sess,
                     hir_map: hir_map.map(|m| m.clone()),
                 };
                 f(&annotation)
             }
             PpmExpandedHygiene => {
                 let annotation = HygieneAnnotation {
-                    sess: sess,
+                    sess,
                 };
                 f(&annotation)
             }
@@ -211,7 +211,7 @@ impl PpSourceMode {
         match *self {
             PpmNormal => {
                 let annotation = NoAnn {
-                    sess: sess,
+                    sess,
                     hir_map: Some(hir_map.clone()),
                 };
                 f(&annotation, hir_map.forest.krate())
@@ -219,7 +219,7 @@ impl PpSourceMode {
 
             PpmIdentified => {
                 let annotation = IdentifiedAnnotation {
-                    sess: sess,
+                    sess,
                     hir_map: Some(hir_map.clone()),
                 };
                 f(&annotation, hir_map.forest.krate())
@@ -235,7 +235,7 @@ impl PpSourceMode {
                                                                  |tcx, _, _, _| {
                     let empty_tables = ty::TypeckTables::empty(None);
                     let annotation = TypedAnnotation {
-                        tcx: tcx,
+                        tcx,
                         tables: Cell::new(&empty_tables)
                     };
                     let _ignore = tcx.dep_graph.in_ignore();
@@ -620,6 +620,15 @@ impl UserIdentifiedItem {
 }
 
 // Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
+//
+// FIXME: Currently the `everybody_loops` transformation is not applied to:
+//  * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are
+//    waiting for miri to fix that.
+//  * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging.
+//    Solving this may require `!` to implement every trait, which relies on the an even more
+//    ambitious form of the closed RFC #1637. See also [#34511].
+//
+// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
 pub struct ReplaceBodyWithLoop {
     within_static_or_const: bool,
 }
@@ -635,14 +644,34 @@ impl ReplaceBodyWithLoop {
         self.within_static_or_const = old_const;
         ret
     }
+
+    fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool {
+        if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output {
+            fn involves_impl_trait(ty: &ast::Ty) -> bool {
+                match ty.node {
+                    ast::TyKind::ImplTrait(_) => true,
+                    ast::TyKind::Slice(ref subty) |
+                    ast::TyKind::Array(ref subty, _) |
+                    ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) |
+                    ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) |
+                    ast::TyKind::Paren(ref subty) => involves_impl_trait(subty),
+                    ast::TyKind::Tup(ref tys) => tys.iter().any(|subty| involves_impl_trait(subty)),
+                    _ => false,
+                }
+            }
+            involves_impl_trait(ty)
+        } else {
+            false
+        }
+    }
 }
 
 impl fold::Folder for ReplaceBodyWithLoop {
     fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind {
         let is_const = match i {
             ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
-            ast::ItemKind::Fn(_, _, ref constness, _, _, _) =>
-                constness.node == ast::Constness::Const,
+            ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) =>
+                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_item_kind(i, s))
@@ -651,8 +680,8 @@ impl fold::Folder for ReplaceBodyWithLoop {
     fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
         let is_const = match i.node {
             ast::TraitItemKind::Const(..) => true,
-            ast::TraitItemKind::Method(ast::MethodSig { ref constness, .. }, _) =>
-                constness.node == ast::Constness::Const,
+            ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
+                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_trait_item(i, s))
@@ -661,8 +690,8 @@ impl fold::Folder for ReplaceBodyWithLoop {
     fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
         let is_const = match i.node {
             ast::ImplItemKind::Const(..) => true,
-            ast::ImplItemKind::Method(ast::MethodSig { ref constness, .. }, _) =>
-                constness.node == ast::Constness::Const,
+            ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) =>
+                constness.node == ast::Constness::Const || Self::should_ignore_fn(decl),
             _ => false,
         };
         self.run(is_const, |s| fold::noop_fold_impl_item(i, s))
@@ -680,7 +709,7 @@ impl fold::Folder for ReplaceBodyWithLoop {
                     })
                     .into_iter()
                     .collect(),
-                rules: rules,
+                rules,
                 id: ast::DUMMY_NODE_ID,
                 span: syntax_pos::DUMMY_SP,
             })
@@ -739,7 +768,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
         hir_map: &tcx.hir,
         cfg: &cfg,
         name: format!("node_{}", code.id()),
-        labelled_edges: labelled_edges,
+        labelled_edges,
     };
 
     match code {
@@ -758,7 +787,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
 
             let lcfg = borrowck_dot::DataflowLabeller {
                 inner: lcfg,
-                variants: variants,
+                variants,
                 borrowck_ctxt: &bccx,
                 analysis_data: &analysis_data,
             };
diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs
new file mode 100644
index 00000000000..061077d05a4
--- /dev/null
+++ b/src/librustc_driver/profile/mod.rs
@@ -0,0 +1,316 @@
+// Copyright 2012-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.
+
+use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
+use std::sync::mpsc::{Receiver};
+use std::io::{Write};
+use rustc::dep_graph::{DepNode};
+use std::time::{Duration, Instant};
+
+pub mod trace;
+
+/// begin a profile thread, if not already running
+pub fn begin() {
+    use std::thread;
+    use std::sync::mpsc::{channel};
+    let (tx, rx) = channel();
+    if profq_set_chan(tx) {
+        thread::spawn(move||profile_queries_thread(rx));
+    }
+}
+
+/// dump files with profiling information to the given base path, and
+/// wait for this dump to complete.
+///
+/// wraps the RPC (send/recv channel logic) of requesting a dump.
+pub fn dump(path:String) {
+    use std::sync::mpsc::{channel};
+    let (tx, rx) = channel();
+    let params = ProfQDumpParams{
+        path, ack:tx,
+        // FIXME: Add another compiler flag to toggle whether this log
+        // is written; false for now
+        dump_profq_msg_log:true,
+    };
+    profq_msg(ProfileQueriesMsg::Dump(params));
+    let _ = rx.recv().unwrap();
+}
+
+// State for parsing recursive trace structure in separate thread, via messages
+#[derive(Clone, Eq, PartialEq)]
+enum ParseState {
+    // No (local) parse state; may be parsing a tree, focused on a
+    // sub-tree that could be anything.
+    Clear,
+    // Have Query information from the last message
+    HaveQuery(trace::Query, Instant),
+    // Have "time-begin" information from the last message (doit flag, and message)
+    HaveTimeBegin(String, Instant),
+    // Have "task-begin" information from the last message
+    HaveTaskBegin(DepNode, Instant),
+}
+struct StackFrame {
+    pub parse_st: ParseState,
+    pub traces:   Vec<trace::Rec>,
+}
+
+fn total_duration(traces: &Vec<trace::Rec>) -> Duration {
+    let mut sum : Duration = Duration::new(0,0);
+    for t in traces.iter() { sum += t.dur_total; }
+    return sum
+}
+
+// profiling thread; retains state (in local variables) and dump traces, upon request.
+fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
+    use self::trace::*;
+    use std::fs::File;
+    use std::time::{Instant};
+
+    let mut profq_msgs : Vec<ProfileQueriesMsg> = vec![];
+    let mut frame : StackFrame = StackFrame{ parse_st:ParseState::Clear, traces:vec![] };
+    let mut stack : Vec<StackFrame> = vec![];
+    loop {
+        let msg = r.recv();
+        if let Err(_recv_err) = msg {
+            // FIXME: Perhaps do something smarter than simply quitting?
+            break
+        };
+        let msg = msg.unwrap();
+        debug!("profile_queries_thread: {:?}", msg);
+
+        // Meta-level versus _actual_ queries messages
+        match msg {
+            ProfileQueriesMsg::Halt => return,
+            ProfileQueriesMsg::Dump(params) => {
+                assert!(stack.len() == 0);
+                assert!(frame.parse_st == ParseState::Clear);
+                {
+                    // write log of all messages
+                    if params.dump_profq_msg_log {
+                        let mut log_file =
+                            File::create(format!("{}.log.txt", params.path)).unwrap();
+                        for m in profq_msgs.iter() {
+                            writeln!(&mut log_file, "{:?}", m).unwrap()
+                        };
+                    }
+
+                    // write HTML file, and counts file
+                    let html_path = format!("{}.html", params.path);
+                    let mut html_file = File::create(&html_path).unwrap();
+
+                    let counts_path = format!("{}.counts.txt", params.path);
+                    let mut counts_file = File::create(&counts_path).unwrap();
+
+                    write!(html_file, "<html>\n").unwrap();
+                    write!(html_file,
+                           "<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n",
+                           "profile_queries.css").unwrap();
+                    write!(html_file, "<style>\n").unwrap();
+                    trace::write_style(&mut html_file);
+                    write!(html_file, "</style>\n").unwrap();
+                    write!(html_file, "</head>\n").unwrap();
+                    write!(html_file, "<body>\n").unwrap();
+                    trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
+                    write!(html_file, "</body>\n</html>\n").unwrap();
+
+                    let ack_path = format!("{}.ack", params.path);
+                    let ack_file = File::create(&ack_path).unwrap();
+                    drop(ack_file);
+
+                    // Tell main thread that we are done, e.g., so it can exit
+                    params.ack.send(()).unwrap();
+                }
+                continue
+            }
+            // Actual query message:
+            msg => {
+                // Record msg in our log
+                profq_msgs.push(msg.clone());
+                // Respond to the message, knowing that we've already handled Halt and Dump, above.
+                match (frame.parse_st.clone(), msg) {
+                    (_,ProfileQueriesMsg::Halt) => unreachable!(),
+                    (_,ProfileQueriesMsg::Dump(_)) => unreachable!(),
+
+                    // Parse State: Clear
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::QueryBegin(span,querymsg)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveQuery
+                            (Query{span:span, msg:querymsg}, start)
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::CacheHit) => {
+                        panic!("parse error: unexpected CacheHit; expected QueryBegin")
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::ProviderBegin) => {
+                        panic!("parse error: expected QueryBegin before beginning a provider")
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::ProviderEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveQuery(q, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::QueryBegin(q, CacheCase::Miss),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_self: duration - dur_extent,
+                                            dur_total: duration,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeBegin(msg)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveTimeBegin(msg, start);
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+                    (_, ProfileQueriesMsg::TimeBegin(_)) =>
+                        panic!("parse error; did not expect time begin here"),
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveTimeBegin(msg, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::TimeBegin(msg),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_total: duration,
+                                            dur_self: duration - dur_extent,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+                    (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") }
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TaskBegin(key)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveTaskBegin(key, start);
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+                    (_, ProfileQueriesMsg::TaskBegin(_)) =>
+                        panic!("parse error; did not expect time begin here"),
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TaskEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveTaskBegin(key, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::TaskBegin(key),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_total: duration,
+                                            dur_self: duration - dur_extent,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+                    (_, ProfileQueriesMsg::TaskEnd) => { panic!("parse error") }
+
+                    // Parse State: HaveQuery
+                    (ParseState::HaveQuery(q,start),
+                     ProfileQueriesMsg::CacheHit) => {
+                        let duration = start.elapsed();
+                        let trace : Rec = Rec{
+                            effect: Effect::QueryBegin(q, CacheCase::Hit),
+                            extent: Box::new(vec![]),
+                            start: start,
+                            dur_self: duration,
+                            dur_total: duration,
+                        };
+                        frame.traces.push( trace );
+                        frame.parse_st = ParseState::Clear;
+                    },
+                    (ParseState::HaveQuery(_,_),
+                     ProfileQueriesMsg::ProviderBegin) => {
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+
+                    //
+                    //
+                    // Parse errors:
+
+                    (ParseState::HaveQuery(q,_),
+                     ProfileQueriesMsg::ProviderEnd) => {
+                        panic!("parse error: unexpected ProviderEnd; \
+                                expected something else to follow BeginQuery for {:?}", q)
+                    },
+                    (ParseState::HaveQuery(q1,_),
+                     ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => {
+                        panic!("parse error: unexpected QueryBegin; \
+                                earlier query is unfinished: {:?} and now {:?}",
+                               q1, Query{span:span2, msg:querymsg2})
+                    },
+
+                    (ParseState::HaveTimeBegin(_, _), _) => {
+                        unreachable!()
+                    },
+                    (ParseState::HaveTaskBegin(_, _), _) => {
+                        unreachable!()
+                    },
+                }
+
+            }
+        }
+    }
+}
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
new file mode 100644
index 00000000000..f5079836c3c
--- /dev/null
+++ b/src/librustc_driver/profile/trace.rs
@@ -0,0 +1,315 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+use syntax_pos::Span;
+use rustc::ty::maps::QueryMsg;
+use std::fs::File;
+use std::time::{Duration, Instant};
+use std::collections::hash_map::HashMap;
+use rustc::dep_graph::{DepNode};
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Query {
+    pub span: Span,
+    pub msg: QueryMsg,
+}
+pub enum Effect {
+    QueryBegin(Query, CacheCase),
+    TimeBegin(String),
+    TaskBegin(DepNode),
+}
+pub enum CacheCase {
+    Hit, Miss
+}
+/// Recursive trace structure
+pub struct Rec {
+    pub effect: Effect,
+    pub start: Instant,
+    pub dur_self: Duration,
+    pub dur_total: Duration,
+    pub extent: Box<Vec<Rec>>,
+}
+pub struct QueryMetric {
+    pub count: usize,
+    pub dur_self: Duration,
+    pub dur_total: Duration,
+}
+
+pub fn cons_of_query_msg(q: &trace::Query) -> String {
+    let s = format!("{:?}", q.msg);
+    let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+    assert!(cons.len() > 0 && cons[0] != "");
+    cons[0].to_string()
+}
+
+pub fn cons_of_key(k: &DepNode) -> String {
+    let s = format!("{:?}", k);
+    let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+    assert!(cons.len() > 0 && cons[0] != "");
+    cons[0].to_string()
+}
+
+// First return value is text; second return value is a CSS class
+pub fn html_of_effect(eff: &Effect) -> (String, String) {
+    match *eff {
+        Effect::TimeBegin(ref msg) => {
+            (msg.clone(),
+             format!("time-begin"))
+        },
+        Effect::TaskBegin(ref key) => {
+            let cons = cons_of_key(key);
+            (cons.clone(), format!("{} task-begin", cons))
+        },
+        Effect::QueryBegin(ref qmsg, ref cc) => {
+            let cons = cons_of_query_msg(qmsg);
+            (cons.clone(),
+             format!("{} {}",
+                     cons,
+                     match *cc {
+                         CacheCase::Hit => "hit",
+                         CacheCase::Miss => "miss",
+                     }))
+        }
+    }
+}
+
+// First return value is text; second return value is a CSS class
+fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
+    use rustc::util::common::duration_to_secs_str;
+    (duration_to_secs_str(dur.clone()),
+     "".to_string()
+    )
+}
+
+fn html_of_fraction(frac: f64) -> (String, String) {
+    let css = {
+        if       frac > 0.50  { format!("frac-50") }
+        else if  frac > 0.40  { format!("frac-40") }
+        else if  frac > 0.30  { format!("frac-30") }
+        else if  frac > 0.20  { format!("frac-20") }
+        else if  frac > 0.10  { format!("frac-10") }
+        else if  frac > 0.05  { format!("frac-05") }
+        else if  frac > 0.02  { format!("frac-02") }
+        else if  frac > 0.01  { format!("frac-01") }
+        else if  frac > 0.001 { format!("frac-001") }
+        else                  { format!("frac-0") }
+    };
+    let percent = frac * 100.0;
+    if percent > 0.1 { (format!("{:.1}%", percent), css) }
+    else { (format!("< 0.1%", ), css) }
+}
+
+fn total_duration(traces: &Vec<Rec>) -> Duration {
+    let mut sum : Duration = Duration::new(0,0);
+    for t in traces.iter() {
+        sum += t.dur_total;
+    }
+    return sum
+}
+
+fn duration_div(nom: Duration, den: Duration) -> f64 {
+    fn to_nanos(d: Duration) -> u64 {
+        d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
+    }
+
+    to_nanos(nom) as f64 / to_nanos(den) as f64
+}
+
+fn write_traces_rec(file: &mut File, traces: &Vec<Rec>, total: Duration, depth: usize) {
+    for t in traces {
+        let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
+        let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
+        let fraction = duration_div(t.dur_total, total);
+        let percent = fraction * 100.0;
+        let (frc_text, frc_css_classes) = html_of_fraction(fraction);
+        write!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">\n",
+               depth,
+               t.extent.len(),
+               /* Heuristic for 'important' CSS class: */
+               if t.extent.len() > 5 || percent >= 1.0 {
+                   " important" }
+               else { "" },
+               eff_css_classes,
+               dur_css_classes,
+               frc_css_classes,
+        ).unwrap();
+        write!(file, "<div class=\"eff\">{}</div>\n", eff_text).unwrap();
+        write!(file, "<div class=\"dur\">{}</div>\n", dur_text).unwrap();
+        write!(file, "<div class=\"frc\">{}</div>\n", frc_text).unwrap();
+        write_traces_rec(file, &t.extent, total, depth + 1);
+        write!(file, "</div>\n").unwrap();
+    }
+}
+
+fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &Vec<Rec>) {
+    for t in traces.iter() {
+        match t.effect {
+            Effect::TimeBegin(ref msg) => {
+                let qm = match counts.get(msg) {
+                    Some(_qm) => { panic!("TimeBegin with non-unique, repeat message") }
+                    None => QueryMetric{
+                        count: 1,
+                        dur_self: t.dur_self,
+                        dur_total: t.dur_total,
+                    }};
+                counts.insert(msg.clone(), qm);
+            },
+            Effect::TaskBegin(ref key) => {
+                let cons = cons_of_key(key);
+                let qm = match counts.get(&cons) {
+                    Some(qm) =>
+                        QueryMetric{
+                            count: qm.count + 1,
+                            dur_self: qm.dur_self + t.dur_self,
+                            dur_total: qm.dur_total + t.dur_total,
+                        },
+                    None => QueryMetric{
+                        count: 1,
+                        dur_self: t.dur_self,
+                        dur_total: t.dur_total,
+                    }};
+                counts.insert(cons, qm);
+            },
+            Effect::QueryBegin(ref qmsg, ref _cc) => {
+                let qcons = cons_of_query_msg(qmsg);
+                let qm = match counts.get(&qcons) {
+                    Some(qm) =>
+                        QueryMetric{
+                            count: qm.count + 1,
+                            dur_total: qm.dur_total + t.dur_total,
+                            dur_self: qm.dur_self + t.dur_self
+                        },
+                    None => QueryMetric{
+                        count: 1,
+                        dur_total: t.dur_total,
+                        dur_self: t.dur_self,
+                    }
+                };
+                counts.insert(qcons, qm);
+            }
+        }
+        compute_counts_rec(counts, &t.extent)
+    }
+}
+
+pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
+    use rustc::util::common::duration_to_secs_str;
+    use std::cmp::Ordering;
+
+    let mut data = vec![];
+    for (ref cons, ref qm) in counts.iter() {
+        data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()));
+    };
+    data.sort_by(|&(_,_,_,self1),&(_,_,_,self2)|
+                 if self1 > self2 { Ordering::Less } else { Ordering::Greater } );
+    for (cons, count, dur_total, dur_self) in data {
+        write!(count_file, "{}, {}, {}, {}\n",
+               cons, count,
+               duration_to_secs_str(dur_total),
+               duration_to_secs_str(dur_self)
+        ).unwrap();
+    }
+}
+
+pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &Vec<Rec>) {
+    let mut counts : HashMap<String,QueryMetric> = HashMap::new();
+    compute_counts_rec(&mut counts, traces);
+    write_counts(counts_file, &mut counts);
+
+    let total : Duration = total_duration(traces);
+    write_traces_rec(html_file, traces, total, 0)
+}
+
+pub fn write_style(html_file: &mut File) {
+    write!(html_file,"{}", "
+body {
+    font-family: sans-serif;
+    background: black;
+}
+.trace {
+    color: black;
+    display: inline-block;
+    border-style: solid;
+    border-color: red;
+    border-width: 1px;
+    border-radius: 5px;
+    padding: 0px;
+    margin: 1px;
+    font-size: 0px;
+}
+.task-begin {
+    border-width: 1px;
+    color: white;
+    border-color: #ff8;
+    font-size: 0px;
+}
+.miss {
+    border-color: red;
+    border-width: 1px;
+}
+.extent-0 {
+    padding: 2px;
+}
+.time-begin {
+    border-width: 4px;
+    font-size: 12px;
+    color: white;
+    border-color: #afa;
+}
+.important {
+    border-width: 3px;
+    font-size: 12px;
+    color: white;
+    border-color: #f77;
+}
+.hit {
+    padding: 0px;
+    border-color: blue;
+    border-width: 3px;
+}
+.eff {
+  color: #fff;
+  display: inline-block;
+}
+.frc {
+  color: #7f7;
+  display: inline-block;
+}
+.dur {
+  display: none
+}
+.frac-50 {
+  padding: 10px;
+  border-width: 10px;
+  font-size: 32px;
+}
+.frac-40 {
+  padding: 8px;
+  border-width: 8px;
+  font-size: 24px;
+}
+.frac-30 {
+  padding: 6px;
+  border-width: 6px;
+  font-size: 18px;
+}
+.frac-20 {
+  padding: 4px;
+  border-width: 6px;
+  font-size: 16px;
+}
+.frac-10 {
+  padding: 2px;
+  border-width: 6px;
+  font-size: 14px;
+}
+").unwrap();
+}
diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs
index bee61bb3980..96264472b5f 100644
--- a/src/librustc_driver/target_features.rs
+++ b/src/librustc_driver/target_features.rs
@@ -25,21 +25,7 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
         cfg.insert((tf, Some(feat)));
     }
 
-    let requested_features = sess.opts.cg.target_feature.split(',');
-    let found_negative = requested_features.clone().any(|r| r == "-crt-static");
-    let found_positive = requested_features.clone().any(|r| r == "+crt-static");
-
-    // If the target we're compiling for requests a static crt by default,
-    // then see if the `-crt-static` feature was passed to disable that.
-    // Otherwise if we don't have a static crt by default then see if the
-    // `+crt-static` feature was passed.
-    let crt_static = if sess.target.target.options.crt_static_default {
-        !found_negative
-    } else {
-        found_positive
-    };
-
-    if crt_static {
+    if sess.crt_static_feature() {
         cfg.insert((tf, Some(Symbol::intern("crt-static"))));
     }
 }
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 91d32dbb84f..0f063542383 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -83,9 +83,9 @@ impl Diagnostic {
 
     pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
         Diagnostic {
-            level: level,
+            level,
             message: vec![(message.to_owned(), Style::NoStyle)],
-            code: code,
+            code,
             span: MultiSpan::new(),
             children: vec![],
             suggestions: vec![],
@@ -93,9 +93,9 @@ impl Diagnostic {
     }
 
     /// Cancel the diagnostic (a structured diagnostic must either be emitted or
-    /// cancelled or it will panic when dropped).
+    /// canceled or it will panic when dropped).
     /// BEWARE: if this DiagnosticBuilder is an error, then creating it will
-    /// bump the error count on the Handler and cancelling it won't undo that.
+    /// bump the error count on the Handler and canceling it won't undo that.
     /// If you want to decrement the error count you should use `Handler::cancel`.
     pub fn cancel(&mut self) {
         self.level = Level::Cancelled;
@@ -105,10 +105,6 @@ impl Diagnostic {
         self.level == Level::Cancelled
     }
 
-    pub fn is_fatal(&self) -> bool {
-        self.level == Level::Fatal
-    }
-
     /// Add a span/label to be included in the resulting snippet.
     /// This is pushed onto the `MultiSpan` that was created when the
     /// diagnostic was first built. If you don't call this function at
@@ -278,18 +274,10 @@ impl Diagnostic {
         self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
     }
 
-    pub fn set_message(&mut self, message: &str) {
-        self.message = vec![(message.to_owned(), Style::NoStyle)];
-    }
-
     pub fn styled_message(&self) -> &Vec<(String, Style)> {
         &self.message
     }
 
-    pub fn level(&self) -> Level {
-        self.level
-    }
-
     /// Used by a lint. Copies over all details *but* the "main
     /// message".
     pub fn copy_details_not_message(&mut self, from: &Diagnostic) {
@@ -306,10 +294,10 @@ impl Diagnostic {
            span: MultiSpan,
            render_span: Option<RenderSpan>) {
         let sub = SubDiagnostic {
-            level: level,
+            level,
             message: vec![(message.to_owned(), Style::NoStyle)],
-            span: span,
-            render_span: render_span,
+            span,
+            render_span,
         };
         self.children.push(sub);
     }
@@ -322,10 +310,10 @@ impl Diagnostic {
                            span: MultiSpan,
                            render_span: Option<RenderSpan>) {
         let sub = SubDiagnostic {
-            level: level,
-            message: message,
-            span: span,
-            render_span: render_span,
+            level,
+            message,
+            span,
+            render_span,
         };
         self.children.push(sub);
     }
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 5d7c5e2829a..2c8d8b4691f 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -98,7 +98,7 @@ impl<'a> DiagnosticBuilder<'a> {
             }
         };
 
-        self.handler.emitter.borrow_mut().emit(&self);
+        self.handler.emit_db(&self);
         self.cancel();
 
         if is_error {
@@ -110,6 +110,22 @@ impl<'a> DiagnosticBuilder<'a> {
         // }
     }
 
+    /// Delay emission of this diagnostic as a bug.
+    ///
+    /// This can be useful in contexts where an error indicates a bug but
+    /// typically this only happens when other compilation errors have already
+    /// happened. In those cases this can be used to defer emission of this
+    /// diagnostic as a bug in the compiler only if no other errors have been
+    /// emitted.
+    ///
+    /// In the meantime, though, callsites are required to deal with the "bug"
+    /// locally in whichever way makes the most sense.
+    pub fn delay_as_bug(&mut self) {
+        self.level = Level::Bug;
+        *self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
+        self.cancel();
+    }
+
     /// Add a span/label to be included in the resulting snippet.
     /// This is pushed onto the `MultiSpan` that was created when the
     /// diagnostic was first built. If you don't call this function at
@@ -178,17 +194,15 @@ impl<'a> DiagnosticBuilder<'a> {
                          code: Option<String>,
                          message: &str)
                          -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder {
-            handler: handler,
-            diagnostic: Diagnostic::new_with_code(level, code, message)
-        }
+        let diagnostic = Diagnostic::new_with_code(level, code, message);
+        DiagnosticBuilder::new_diagnostic(handler, diagnostic)
     }
 
-    pub fn into_diagnostic(mut self) -> Diagnostic {
-        // annoyingly, the Drop impl means we can't actually move
-        let result = self.diagnostic.clone();
-        self.cancel();
-        result
+    /// Creates a new `DiagnosticBuilder` with an already constructed
+    /// diagnostic.
+    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
+                         -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder { handler, diagnostic }
     }
 }
 
@@ -198,7 +212,7 @@ impl<'a> Debug for DiagnosticBuilder<'a> {
     }
 }
 
-/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
+/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or canceled
 /// or we emit a bug.
 impl<'a> Drop for DiagnosticBuilder<'a> {
     fn drop(&mut self) {
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 3cfa635f5b2..53d90531cc9 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -120,7 +120,7 @@ impl EmitterWriter {
         if color_config.use_color() {
             let dst = Destination::from_stderr();
             EmitterWriter {
-                dst: dst,
+                dst,
                 cm: code_map,
             }
         } else {
@@ -156,7 +156,7 @@ impl EmitterWriter {
                     }
                     // We don't have a line yet, create one
                     slot.lines.push(Line {
-                        line_index: line_index,
+                        line_index,
                         annotations: vec![ann],
                     });
                     slot.lines.sort();
@@ -165,9 +165,9 @@ impl EmitterWriter {
             }
             // This is the first time we're seeing the file
             file_vec.push(FileWithAnnotatedLines {
-                file: file,
+                file,
                 lines: vec![Line {
-                                line_index: line_index,
+                                line_index,
                                 annotations: vec![ann],
                             }],
                 multiline_depth: 0,
@@ -311,7 +311,9 @@ impl EmitterWriter {
         if line.annotations.len() == 1 {
             if let Some(ref ann) = line.annotations.get(0) {
                 if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
-                    if source_string[0..ann.start_col].trim() == "" {
+                    if source_string.chars()
+                                    .take(ann.start_col)
+                                    .all(|c| c.is_whitespace()) {
                         let style = if ann.is_primary {
                             Style::UnderlinePrimary
                         } else {
@@ -822,7 +824,7 @@ impl EmitterWriter {
             .map(|_| " ")
             .collect::<String>();
 
-        /// Return wether `style`, or the override if present and the style is `NoStyle`.
+        /// Return whether `style`, or the override if present and the style is `NoStyle`.
         fn style_or_override(style: Style, override_style: Option<Style>) -> Style {
             if let Some(o) = override_style {
                 if style == Style::NoStyle {
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 159d2c7a2df..870bb01bb9f 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_errors"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -19,10 +16,11 @@
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(range_contains)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(conservative_impl_trait)]
 
 extern crate term;
+#[cfg(unix)]
 extern crate libc;
 extern crate serialize as rustc_serialize;
 extern crate syntax_pos;
@@ -35,11 +33,12 @@ use emitter::{Emitter, EmitterWriter};
 
 use std::borrow::Cow;
 use std::cell::{RefCell, Cell};
-use std::{error, fmt};
+use std::mem;
 use std::rc::Rc;
+use std::{error, fmt};
 
-pub mod diagnostic;
-pub mod diagnostic_builder;
+mod diagnostic;
+mod diagnostic_builder;
 pub mod emitter;
 mod snippet;
 pub mod registry;
@@ -111,7 +110,7 @@ impl CodeSuggestion {
     }
 
     /// Returns the number of substitutions
-    pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
+    fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a {
         self.substitution_parts.iter().map(|sub| sub.span)
     }
 
@@ -155,8 +154,8 @@ impl CodeSuggestion {
         let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap();
         let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap();
         let bounding_span = Span {
-            lo: lo,
-            hi: hi,
+            lo,
+            hi,
             ctxt: NO_EXPANSION,
         };
         let lines = cm.span_to_lines(bounding_span).unwrap();
@@ -217,8 +216,10 @@ impl CodeSuggestion {
             if !buf.ends_with('\n') {
                 push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
             }
-            // remove trailing newline
-            buf.pop();
+            // remove trailing newlines
+            while buf.ends_with('\n') {
+                buf.pop();
+            }
         }
         bufs
     }
@@ -260,7 +261,7 @@ impl error::Error for ExplicitBug {
     }
 }
 
-pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, StringPart};
+pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString};
 pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
@@ -272,7 +273,8 @@ pub struct Handler {
     pub can_emit_warnings: bool,
     treat_err_as_bug: bool,
     continue_after_error: Cell<bool>,
-    delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
+    delayed_span_bug: RefCell<Option<Diagnostic>>,
+    tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
 }
 
 impl Handler {
@@ -292,10 +294,11 @@ impl Handler {
         Handler {
             err_count: Cell::new(0),
             emitter: RefCell::new(e),
-            can_emit_warnings: can_emit_warnings,
-            treat_err_as_bug: treat_err_as_bug,
+            can_emit_warnings,
+            treat_err_as_bug,
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
+            tracked_diagnostics: RefCell::new(None),
         }
     }
 
@@ -437,8 +440,9 @@ impl Handler {
         if self.treat_err_as_bug {
             self.span_bug(sp, msg);
         }
-        let mut delayed = self.delayed_span_bug.borrow_mut();
-        *delayed = Some((sp.into(), msg.to_string()));
+        let mut diagnostic = Diagnostic::new(Level::Bug, msg);
+        diagnostic.set_span(sp.into());
+        *self.delayed_span_bug.borrow_mut() = Some(diagnostic);
     }
     pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Bug);
@@ -489,7 +493,7 @@ impl Handler {
         self.bug(&format!("unimplemented {}", msg));
     }
 
-    pub fn bump_err_count(&self) {
+    fn bump_err_count(&self) {
         self.panic_if_treat_err_as_bug();
         self.err_count.set(self.err_count.get() + 1);
     }
@@ -505,14 +509,9 @@ impl Handler {
         let s;
         match self.err_count.get() {
             0 => {
-                let delayed_bug = self.delayed_span_bug.borrow();
-                match *delayed_bug {
-                    Some((ref span, ref errmsg)) => {
-                        self.span_bug(span.clone(), errmsg);
-                    }
-                    _ => {}
+                if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
+                    DiagnosticBuilder::new_diagnostic(self, bug).emit();
                 }
-
                 return;
             }
             1 => s = "aborting due to previous error".to_string(),
@@ -545,6 +544,24 @@ impl Handler {
             self.abort_if_errors();
         }
     }
+
+    pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
+        where F: FnOnce() -> R
+    {
+        let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(),
+                                Some(Vec::new()));
+        let ret = f();
+        let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev)
+            .unwrap();
+        (ret, diagnostics)
+    }
+
+    fn emit_db(&self, db: &DiagnosticBuilder) {
+        if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
+            list.push((**db).clone());
+        }
+        self.emitter.borrow_mut().emit(db);
+    }
 }
 
 
@@ -569,7 +586,7 @@ impl fmt::Display for Level {
 }
 
 impl Level {
-    pub fn color(self) -> term::color::Color {
+    fn color(self) -> term::color::Color {
         match self {
             Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED,
             Warning => {
@@ -596,12 +613,3 @@ impl Level {
         }
     }
 }
-
-pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T
-    where M: FnOnce() -> String
-{
-    match opt {
-        Some(t) => t,
-        None => diag.bug(&msg()),
-    }
-}
diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs
index 3c5a6c031e1..52e3fcc1b47 100644
--- a/src/librustc_errors/snippet.rs
+++ b/src/librustc_errors/snippet.rs
@@ -141,7 +141,7 @@ pub struct Annotation {
 }
 
 impl Annotation {
-    /// Wether this annotation is a vertical line placeholder.
+    /// Whether this annotation is a vertical line placeholder.
     pub fn is_line(&self) -> bool {
         if let AnnotationType::MultilineLine(_) = self.annotation_type {
             true
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 04192c35ef3..1d58d179960 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -76,7 +76,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     // Find annotations supplied by user (if any).
     let (if_this_changed, then_this_would_need) = {
-        let mut visitor = IfThisChanged { tcx: tcx,
+        let mut visitor = IfThisChanged { tcx,
                                           if_this_changed: vec![],
                                           then_this_would_need: vec![] };
         visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs);
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
index f30a0f553b9..94400890c56 100644
--- a/src/librustc_incremental/calculate_svh/mod.rs
+++ b/src/librustc_incremental/calculate_svh/mod.rs
@@ -62,10 +62,6 @@ impl IncrementalHashesMap {
         }
     }
 
-    pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> {
-        self.hashes.get(k)
-    }
-
     pub fn insert(&mut self, k: DepNode, v: Fingerprint) {
         assert!(self.hashes.insert(k, v).is_none());
     }
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index ac3149b90b8..8870033095c 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -10,9 +10,6 @@
 
 //! Support for serializing the dep-graph and reloading it.
 
-#![crate_name = "rustc_incremental"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -44,4 +41,3 @@ pub use persist::save_trans_partition;
 pub use persist::save_work_products;
 pub use persist::in_incr_comp_dir;
 pub use persist::finalize_session_directory;
-pub use persist::delete_workproduct_files;
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 3f3dc10365c..126057fd043 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -83,15 +83,15 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("query-nodes: {:?}", query.nodes());
     let krate = tcx.hir.krate();
     let mut dirty_clean_visitor = DirtyCleanVisitor {
-        tcx: tcx,
+        tcx,
         query: &query,
-        dirty_inputs: dirty_inputs,
+        dirty_inputs,
         checked_attrs: FxHashSet(),
     };
     krate.visit_all_item_likes(&mut dirty_clean_visitor);
 
     let mut all_attrs = FindAllAttrs {
-        tcx: tcx,
+        tcx,
         attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
         found_attrs: vec![],
     };
@@ -243,15 +243,15 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>(
     tcx.dep_graph.with_ignore(||{
         let krate = tcx.hir.krate();
         let mut dirty_clean_visitor = DirtyCleanMetadataVisitor {
-            tcx: tcx,
-            prev_metadata_hashes: prev_metadata_hashes,
-            current_metadata_hashes: current_metadata_hashes,
+            tcx,
+            prev_metadata_hashes,
+            current_metadata_hashes,
             checked_attrs: FxHashSet(),
         };
         intravisit::walk_crate(&mut dirty_clean_visitor, krate);
 
         let mut all_attrs = FindAllAttrs {
-            tcx: tcx,
+            tcx,
             attr_names: vec![ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA],
             found_attrs: vec![],
         };
diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs
index 0e8ffb9ee3c..9d762a74bfe 100644
--- a/src/librustc_incremental/persist/hash.rs
+++ b/src/librustc_incremental/persist/hash.rs
@@ -38,8 +38,8 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
                incremental_hashes_map: &'a IncrementalHashesMap)
                -> Self {
         HashContext {
-            tcx: tcx,
-            incremental_hashes_map: incremental_hashes_map,
+            tcx,
+            incremental_hashes_map,
             metadata_hashes: FxHashMap(),
             crate_hashes: FxHashMap(),
         }
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index c03a0ab4ba2..5c1582daa78 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -28,4 +28,3 @@ pub use self::load::load_dep_graph;
 pub use self::save::save_dep_graph;
 pub use self::save::save_work_products;
 pub use self::work_product::save_trans_partition;
-pub use self::work_product::delete_workproduct_files;
diff --git a/src/librustc_incremental/persist/preds/compress/classify/mod.rs b/src/librustc_incremental/persist/preds/compress/classify/mod.rs
index 559bdbdd1e2..aa29afd543c 100644
--- a/src/librustc_incremental/persist/preds/compress/classify/mod.rs
+++ b/src/librustc_incremental/persist/preds/compress/classify/mod.rs
@@ -45,7 +45,7 @@ impl<'a, 'g, N, I, O> Classify<'a, 'g, N, I, O>
 {
     pub(super) fn new(r: &'a mut GraphReduce<'g, N, I, O>) -> Self {
         Classify {
-            r: r,
+            r,
             colors: vec![Color::White; r.in_graph.len_nodes()],
             stack: vec![],
             dag: Dag {
diff --git a/src/librustc_incremental/persist/preds/compress/construct.rs b/src/librustc_incremental/persist/preds/compress/construct.rs
index 394be74f783..0ad8d178916 100644
--- a/src/librustc_incremental/persist/preds/compress/construct.rs
+++ b/src/librustc_incremental/persist/preds/compress/construct.rs
@@ -14,7 +14,7 @@
 //! representation of the DAG):
 //!
 //! - SCCs, in the form of a union-find repr that can convert each node to
-//!   its *cycle head* (an arbitrarly chosen representative from the cycle)
+//!   its *cycle head* (an arbitrarily chosen representative from the cycle)
 //! - a vector of *leaf nodes*, just a convenience
 //! - a vector of *parents* for each node (in some cases, nodes have no parents,
 //!   or their parent is another member of same cycle; in that case, the vector
diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs
index f7b6b7376d1..5483134523c 100644
--- a/src/librustc_incremental/persist/preds/mod.rs
+++ b/src/librustc_incremental/persist/preds/mod.rs
@@ -103,8 +103,8 @@ impl<'q> Predecessors<'q> {
 
         Predecessors {
             reduced_graph: graph,
-            bootstrap_outputs: bootstrap_outputs,
-            hashes: hashes,
+            bootstrap_outputs,
+            hashes,
         }
     }
 }
diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs
index 8f99ce91a67..e20d7a006b0 100644
--- a/src/librustc_incremental/persist/work_product.rs
+++ b/src/librustc_incremental/persist/work_product.rs
@@ -57,7 +57,7 @@ pub fn save_trans_partition(sess: &Session,
     let work_product = WorkProduct {
         cgu_name: cgu_name.to_string(),
         input_hash: partition_hash,
-        saved_files: saved_files,
+        saved_files,
     };
 
     sess.dep_graph.insert_work_product(&work_product_id, work_product);
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 83c00c178a0..5ef277f02ac 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -19,9 +19,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_lint"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -45,10 +42,10 @@ extern crate rustc_back;
 extern crate rustc_const_eval;
 extern crate syntax_pos;
 
-pub use rustc::lint;
-pub use rustc::middle;
-pub use rustc::session;
-pub use rustc::util;
+use rustc::lint;
+use rustc::middle;
+use rustc::session;
+use rustc::util;
 
 use session::Session;
 use lint::LintId;
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 195bd2acce0..cbc4ebe90fd 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -160,21 +160,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
         };
 
         let mut fn_warned = false;
-        let maybe_def = match expr.node {
-            hir::ExprCall(ref callee, _) => {
-                match callee.node {
-                    hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)),
-                    _ => None
-                }
-            },
-            hir::ExprMethodCall(..) => {
-                cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
-            },
-            _ => { None }
-        };
-        if let Some(def) = maybe_def {
-            let def_id = def.def_id();
-            fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+        if cx.tcx.sess.features.borrow().fn_must_use {
+            let maybe_def = match expr.node {
+                hir::ExprCall(ref callee, _) => {
+                    match callee.node {
+                        hir::ExprPath(ref qpath) => {
+                            Some(cx.tables.qpath_def(qpath, callee.hir_id))
+                        },
+                        _ => None
+                    }
+                },
+                hir::ExprMethodCall(..) => {
+                    cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
+                },
+                _ => None
+            };
+            if let Some(def) = maybe_def {
+                let def_id = def.def_id();
+                fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+            }
         }
 
         if !(ty_warned || fn_warned) {
diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs
index 0b24e55541b..6c3626cd880 100644
--- a/src/librustc_llvm/archive_ro.rs
+++ b/src/librustc_llvm/archive_ro.rs
@@ -94,7 +94,7 @@ impl<'a> Iterator for Iter<'a> {
             ::last_error().map(Err)
         } else {
             Some(Ok(Child {
-                ptr: ptr,
+                ptr,
                 _data: marker::PhantomData,
             }))
         }
diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs
index c5276e0c971..c5cdf656692 100644
--- a/src/librustc_llvm/diagnostic.rs
+++ b/src/librustc_llvm/diagnostic.rs
@@ -82,12 +82,12 @@ impl OptimizationDiagnostic {
         }
 
         OptimizationDiagnostic {
-            kind: kind,
+            kind,
             pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
-            function: function,
-            line: line,
-            column: column,
-            filename: filename,
+            function,
+            line,
+            column,
+            filename,
             message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")
         }
     }
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 5b823f91f5f..3c3e627ee4b 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -13,9 +13,6 @@
 #![allow(non_snake_case)]
 #![allow(dead_code)]
 
-#![crate_name = "rustc_llvm"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -38,9 +35,7 @@ pub use self::TypeKind::*;
 pub use self::AtomicRmwBinOp::*;
 pub use self::MetadataType::*;
 pub use self::CodeGenOptSize::*;
-pub use self::DiagnosticKind::*;
 pub use self::CallConv::*;
-pub use self::DiagnosticSeverity::*;
 pub use self::Linkage::*;
 
 use std::str::FromStr;
@@ -51,7 +46,7 @@ use libc::{c_uint, c_char, size_t};
 
 pub mod archive_ro;
 pub mod diagnostic;
-pub mod ffi;
+mod ffi;
 
 pub use ffi::*;
 
@@ -120,7 +115,7 @@ impl FromStr for ArchiveKind {
 
 #[allow(missing_copy_implementations)]
 pub enum RustString_opaque {}
-pub type RustStringRef = *mut RustString_opaque;
+type RustStringRef = *mut RustString_opaque;
 type RustStringRepr = *mut RefCell<Vec<u8>>;
 
 /// Appending to a Rust string -- used by RawRustStringOstream.
@@ -199,8 +194,8 @@ impl Attribute {
 
 // Memory-managed interface to target data.
 
-pub struct TargetData {
-    pub lltd: TargetDataRef,
+struct TargetData {
+    lltd: TargetDataRef,
 }
 
 impl Drop for TargetData {
@@ -211,7 +206,7 @@ impl Drop for TargetData {
     }
 }
 
-pub fn mk_target_data(string_rep: &str) -> TargetData {
+fn mk_target_data(string_rep: &str) -> TargetData {
     let string_rep = CString::new(string_rep).unwrap();
     TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
 }
@@ -272,7 +267,7 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
     }
 }
 
-pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
+fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
     unsafe {
         let num_params = LLVMCountParams(llfn);
         let mut params = Vec::with_capacity(num_params as usize);
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 67b459ea18f..40b75be36fe 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -15,7 +15,6 @@ owning_ref = "0.3.3"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 6c02ac7eafe..b1b3e92347a 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -53,7 +53,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> {
             body: lazy_body,
             tables: lazy_tables,
             nested_bodies: lazy_nested_bodies,
-            rvalue_promotable_to_static: rvalue_promotable_to_static
+            rvalue_promotable_to_static,
         })
     }
 }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index d15843b4f31..4c25d03b441 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -162,8 +162,8 @@ enum LoadResult {
 impl<'a> CrateLoader<'a> {
     pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
         CrateLoader {
-            sess: sess,
-            cstore: cstore,
+            sess,
+            cstore,
             next_crate_num: cstore.next_crate_num(),
             local_crate_name: Symbol::intern(local_crate_name),
         }
@@ -184,7 +184,7 @@ impl<'a> CrateLoader<'a> {
                 };
                 Some(ExternCrateInfo {
                     ident: i.ident.name,
-                    name: name,
+                    name,
                     id: i.id,
                     dep_kind: if attr::contains_name(&i.attrs, "no_link") {
                         DepKind::UnexportedMacrosOnly
@@ -325,25 +325,25 @@ impl<'a> CrateLoader<'a> {
             });
 
         let mut cmeta = cstore::CrateMetadata {
-            name: name,
+            name,
             extern_crate: Cell::new(None),
             def_path_table: Rc::new(def_path_table),
-            exported_symbols: exported_symbols,
-            trait_impls: trait_impls,
+            exported_symbols,
+            trait_impls,
             proc_macros: crate_root.macro_derive_registrar.map(|_| {
                 self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
             }),
             root: crate_root,
             blob: metadata,
             cnum_map: RefCell::new(cnum_map),
-            cnum: cnum,
+            cnum,
             codemap_import_info: RefCell::new(vec![]),
             attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
             dep_kind: Cell::new(dep_kind),
             source: cstore::CrateSource {
-                dylib: dylib,
-                rlib: rlib,
-                rmeta: rmeta,
+                dylib,
+                rlib,
+                rmeta,
             },
             // Initialize this with an empty set. The field is populated below
             // after we were able to deserialize its contents.
@@ -388,14 +388,14 @@ impl<'a> CrateLoader<'a> {
             info!("falling back to a load");
             let mut locate_ctxt = locator::Context {
                 sess: self.sess,
-                span: span,
-                ident: ident,
+                span,
+                ident,
                 crate_name: name,
                 hash: hash.map(|a| &*a),
                 filesearch: self.sess.target_filesearch(path_kind),
                 target: &self.sess.target.target,
                 triple: &self.sess.opts.target_triple,
-                root: root,
+                root,
                 rejected_via_hash: vec![],
                 rejected_via_triple: vec![],
                 rejected_via_kind: vec![],
@@ -547,7 +547,7 @@ impl<'a> CrateLoader<'a> {
         let mut target_only = false;
         let mut locate_ctxt = locator::Context {
             sess: self.sess,
-            span: span,
+            span,
             ident: info.ident,
             crate_name: info.name,
             hash: None,
@@ -596,9 +596,9 @@ impl<'a> CrateLoader<'a> {
         };
 
         ExtensionCrate {
-            metadata: metadata,
+            metadata,
             dylib: dylib.map(|p| p.0),
-            target_only: target_only,
+            target_only,
         }
     }
 
@@ -1221,9 +1221,9 @@ impl<'a> CrateLoader<'a> {
                 .collect();
             let lib = NativeLibrary {
                 name: n,
-                kind: kind,
-                cfg: cfg,
-                foreign_items: foreign_items,
+                kind,
+                cfg,
+                foreign_items,
             };
             register_native_lib(self.sess, self.cstore, Some(m.span), lib);
         }
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index fb43f91c46d..0ed8ab2bc55 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -32,7 +32,7 @@ use syntax_pos;
 
 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
 pub use rustc::middle::cstore::NativeLibraryKind::*;
-pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
+pub use rustc::middle::cstore::{CrateSource, LibSource};
 
 pub use cstore_impl::{provide, provide_local};
 
@@ -114,7 +114,7 @@ impl CStore {
             statically_included_foreign_items: RefCell::new(FxHashSet()),
             dllimport_foreign_items: RefCell::new(FxHashSet()),
             visible_parent_map: RefCell::new(FxHashMap()),
-            metadata_loader: metadata_loader,
+            metadata_loader,
         }
     }
 
@@ -142,14 +142,6 @@ impl CStore {
         }
     }
 
-    pub fn reset(&self) {
-        self.metas.borrow_mut().clear();
-        self.extern_mod_crate_map.borrow_mut().clear();
-        self.used_libraries.borrow_mut().clear();
-        self.used_link_args.borrow_mut().clear();
-        self.statically_included_foreign_items.borrow_mut().clear();
-    }
-
     pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
         self.push_dependencies_in_postorder(&mut ordering, krate);
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d2ab9b2fbce..ad320a7ff3d 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -137,6 +137,8 @@ provide! { <'tcx> tcx, def_id, cdata,
 
     dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) }
     is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) }
+    is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) }
+    has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
 }
 
@@ -282,7 +284,7 @@ impl CrateStore for cstore::CStore {
     {
         self.get_crate_data(cnum).root.plugin_registrar_fn.map(|index| DefId {
             krate: cnum,
-            index: index
+            index,
         })
     }
 
@@ -290,7 +292,7 @@ impl CrateStore for cstore::CStore {
     {
         self.get_crate_data(cnum).root.macro_derive_registrar.map(|index| DefId {
             krate: cnum,
-            index: index
+            index,
         })
     }
 
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index ad3a9dd9fef..73b2e972b93 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -69,7 +69,7 @@ pub trait Metadata<'a, 'tcx>: Copy {
             opaque: opaque::Decoder::new(self.raw_bytes(), pos),
             cdata: self.cdata(),
             sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
-            tcx: tcx,
+            tcx,
             last_filemap_index: 0,
             lazy_state: LazyState::NoNode,
         }
@@ -468,7 +468,7 @@ impl<'a, 'tcx> CrateMetadata {
     fn local_def_id(&self, index: DefIndex) -> DefId {
         DefId {
             krate: self.cnum,
-            index: index,
+            index,
         }
     }
 
@@ -703,7 +703,7 @@ impl<'a, 'tcx> CrateMetadata {
                         for child_index in child.children.decode((self, sess)) {
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
-                                    def: def,
+                                    def,
                                     ident: Ident::with_empty_ctxt(self.item_name(child_index)),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                 });
@@ -835,8 +835,8 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssociatedItem {
-            name: name,
-            kind: kind,
+            name,
+            kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
             def_id: self.local_def_id(id),
@@ -892,7 +892,7 @@ impl<'a, 'tcx> CrateMetadata {
         if def_key.disambiguated_data.data == DefPathData::StructCtor {
             item = self.entry(def_key.parent.unwrap());
         }
-        let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
+        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
         let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
         if vec_.len() < node_index + 1 {
             vec_.resize(node_index + 1, None);
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 8a753a0ae4b..1dc5d695348 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -422,16 +422,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 None
             },
 
-            crate_deps: crate_deps,
-            dylib_dependency_formats: dylib_dependency_formats,
-            lang_items: lang_items,
-            lang_items_missing: lang_items_missing,
-            native_libraries: native_libraries,
-            codemap: codemap,
-            def_path_table: def_path_table,
-            impls: impls,
-            exported_symbols: exported_symbols,
-            index: index,
+            crate_deps,
+            dylib_dependency_formats,
+            lang_items,
+            lang_items_missing,
+            native_libraries,
+            codemap,
+            def_path_table,
+            impls,
+            exported_symbols,
+            index,
         });
 
         let total_bytes = self.position();
@@ -719,15 +719,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: arg_names,
+                        arg_names,
                         sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
                 };
                 EntryKind::Method(self.lazy(&MethodData {
-                    fn_data: fn_data,
-                    container: container,
+                    fn_data,
+                    container,
                     has_self: trait_item.method_has_self_argument,
                 }))
             }
@@ -735,7 +735,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         };
 
         Entry {
-            kind: kind,
+            kind,
             visibility: self.lazy(&trait_item.vis),
             span: self.lazy(&ast_item.span),
             attributes: self.encode_attributes(&ast_item.attrs),
@@ -805,8 +805,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     bug!()
                 };
                 EntryKind::Method(self.lazy(&MethodData {
-                    fn_data: fn_data,
-                    container: container,
+                    fn_data,
+                    container,
                     has_self: impl_item.method_has_self_argument,
                 }))
             }
@@ -828,7 +828,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         };
 
         Entry {
-            kind: kind,
+            kind,
             visibility: self.lazy(&impl_item.vis),
             span: self.lazy(&ast_item.span),
             attributes: self.encode_attributes(&ast_item.attrs),
@@ -915,7 +915,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             }
             hir::ItemFn(_, _, constness, .., body) => {
                 let data = FnData {
-                    constness: constness,
+                    constness,
                     arg_names: self.encode_fn_arg_names_for_body(body),
                     sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
@@ -946,7 +946,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 EntryKind::Struct(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
-                    struct_ctor: struct_ctor,
+                    struct_ctor,
                     ctor_sig: None,
                 }), repr_options)
             }
@@ -998,10 +998,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     });
 
                 let data = ImplData {
-                    polarity: polarity,
-                    defaultness: defaultness,
+                    polarity,
+                    defaultness,
                     parent_impl: parent,
-                    coerce_unsized_info: coerce_unsized_info,
+                    coerce_unsized_info,
                     trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
                 };
 
@@ -1023,7 +1023,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         };
 
         Entry {
-            kind: kind,
+            kind,
             visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
             span: self.lazy(&item.span),
             attributes: self.encode_attributes(&item.attrs),
@@ -1333,7 +1333,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         debug!("IsolatedEncoder::encode_impls()");
         let tcx = self.tcx;
         let mut visitor = ImplVisitor {
-            tcx: tcx,
+            tcx,
             impls: FxHashMap(),
         };
         tcx.hir.krate().visit_all_item_likes(&mut visitor);
@@ -1412,7 +1412,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         };
 
         Entry {
-            kind: kind,
+            kind,
             visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
             span: self.lazy(&nitem.span),
             attributes: self.encode_attributes(&nitem.attrs),
@@ -1653,14 +1653,14 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let (root, metadata_hashes) = {
         let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
-            tcx: tcx,
-            link_meta: link_meta,
-            exported_symbols: exported_symbols,
+            tcx,
+            link_meta,
+            exported_symbols,
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
             metadata_hashes: EncodedMetadataHashes::new(),
-            compute_ich: compute_ich,
+            compute_ich,
         };
 
         // Encode the rustc version string in a predictable location.
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index ebf9910e9c9..69fbc935461 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -100,32 +100,6 @@ impl<'tcx> LazySeq<Index> {
             Some(Lazy::with_position(position as usize))
         }
     }
-
-    pub fn iter_enumerated<'a>(&self,
-                               bytes: &'a [u8])
-                               -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
-        let words = &bytes_to_words(&bytes[self.position..])[..self.len];
-        let lo_count = u32::from_le(words[0].get()) as usize;
-        let lo = &words[1 .. lo_count + 1];
-        let hi = &words[1 + lo_count ..];
-
-        lo.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
-            if pos == u32::MAX {
-                None
-            } else {
-                let pos = u32::from_le(pos) as usize;
-                Some((DefIndex::new(index), Lazy::with_position(pos)))
-            }
-        }).chain(hi.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| {
-            if pos == u32::MAX {
-                None
-            } else {
-                let pos = u32::from_le(pos) as usize;
-                Some((DefIndex::new(index + DefIndexAddressSpace::High.start()),
-                                    Lazy::with_position(pos)))
-            }
-        }))
-    }
 }
 
 #[repr(packed)]
diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs
index 2db9c6a4ff8..1d2b6cc33d4 100644
--- a/src/librustc_metadata/index_builder.rs
+++ b/src/librustc_metadata/index_builder.rs
@@ -92,7 +92,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
         IndexBuilder {
             items: Index::new(ecx.tcx.hir.definitions().def_index_counts_lo_hi()),
-            ecx: ecx,
+            ecx,
         }
     }
 
@@ -137,7 +137,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
         if let Some(hash) = fingerprint {
             ecx.metadata_hashes.hashes.push(EncodedMetadataHash {
                 def_index: id.index,
-                hash: hash,
+                hash,
             });
         }
 
diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs
index c4116489357..b9ad9086c03 100644
--- a/src/librustc_metadata/isolated_encoder.rs
+++ b/src/librustc_metadata/isolated_encoder.rs
@@ -32,8 +32,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         let tcx = ecx.tcx;
         let compute_ich = ecx.compute_ich;
         IsolatedEncoder {
-            tcx: tcx,
-            ecx: ecx,
+            tcx,
+            ecx,
             hcx: if compute_ich {
                 // We are always hashing spans for things in metadata because
                 // don't know if a downstream crate will use them or not.
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 99b718ea07b..f79abecf9da 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_metadata"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -42,13 +39,10 @@ extern crate proc_macro;
 #[macro_use]
 extern crate rustc;
 extern crate rustc_back;
-extern crate rustc_const_math;
 extern crate rustc_data_structures;
 
 mod diagnostics;
 
-pub use rustc::middle;
-
 mod astencode;
 mod index_builder;
 mod index;
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 9bcf590eb8b..19f7cb0ee23 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -306,10 +306,6 @@ impl<'a> Context<'a> {
         self.find_library_crate()
     }
 
-    pub fn load_library_crate(&mut self) -> Library {
-        self.find_library_crate().unwrap_or_else(|| self.report_errs())
-    }
-
     pub fn report_errs(&mut self) -> ! {
         let add = match self.root {
             &None => String::new(),
@@ -518,9 +514,9 @@ impl<'a> Context<'a> {
             if let Some((h, m)) = slot {
                 libraries.insert(h,
                                  Library {
-                                     dylib: dylib,
-                                     rlib: rlib,
-                                     rmeta: rmeta,
+                                     dylib,
+                                     rlib,
+                                     rmeta,
                                      metadata: m,
                                  });
             }
@@ -808,10 +804,10 @@ impl<'a> Context<'a> {
         match slot {
             Some((_, metadata)) => {
                 Some(Library {
-                    dylib: dylib,
-                    rlib: rlib,
-                    rmeta: rmeta,
-                    metadata: metadata,
+                    dylib,
+                    rlib,
+                    rmeta,
+                    metadata,
                 })
             }
             None => None,
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 0b670121ba2..b71f4d0d98c 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -84,7 +84,7 @@ pub struct Lazy<T> {
 impl<T> Lazy<T> {
     pub fn with_position(position: usize) -> Lazy<T> {
         Lazy {
-            position: position,
+            position,
             _marker: PhantomData,
         }
     }
@@ -141,8 +141,8 @@ impl<T> LazySeq<T> {
 
     pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> {
         LazySeq {
-            len: len,
-            position: position,
+            len,
+            position,
             _marker: PhantomData,
         }
     }
@@ -199,7 +199,7 @@ pub struct Tracked<T> {
 impl<T> Tracked<T> {
     pub fn new(state: T) -> Tracked<T> {
         Tracked {
-            state: state,
+            state,
         }
     }
 
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 6e42e02d510..49e626c5400 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -15,6 +15,7 @@ rustc = { path = "../librustc" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_errors = { path = "../librustc_errors" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
new file mode 100644
index 00000000000..eda2bacb11f
--- /dev/null
+++ b/src/librustc_mir/borrow_check.rs
@@ -0,0 +1,1258 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This query borrow-checks the MIR to (further) ensure it is not broken.
+
+use rustc::hir::def_id::{DefId};
+use rustc::infer::{InferCtxt};
+use rustc::ty::{self, TyCtxt, ParamEnv};
+use rustc::ty::maps::Providers;
+use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue};
+use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
+use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
+use rustc::mir::transform::{MirSource};
+
+use rustc_data_structures::indexed_set::{self, IdxSetBuf};
+use rustc_data_structures::indexed_vec::{Idx};
+
+use syntax::ast::{self};
+use syntax_pos::{DUMMY_SP, Span};
+
+use dataflow::{do_dataflow};
+use dataflow::{MoveDataParamEnv};
+use dataflow::{BitDenotation, BlockSets, DataflowResults, DataflowResultsConsumer};
+use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::{Borrows, BorrowData, BorrowIndex};
+use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use util::borrowck_errors::{BorrowckErrors, Origin};
+
+use self::MutateMode::{JustWrite, WriteAndRead};
+use self::ConsumeKind::{Consume};
+
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        mir_borrowck,
+        ..*providers
+    };
+}
+
+fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
+    let mir = tcx.mir_validated(def_id);
+    let src = MirSource::from_local_def_id(tcx, def_id);
+    debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id()));
+
+    let mir: &Mir<'tcx> = &mir.borrow();
+    if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.debugging_opts.borrowck_mir {
+        return;
+    }
+
+    let id = src.item_id();
+    let attributes = tcx.get_attrs(def_id);
+    let param_env = tcx.param_env(def_id);
+    tcx.infer_ctxt().enter(|_infcx| {
+
+        let move_data = MoveData::gather_moves(mir, tcx, param_env);
+        let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
+        let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+        let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                       Borrows::new(tcx, mir),
+                                       |bd, i| bd.location(i));
+        let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                     MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                                     |bd, i| &bd.move_data().move_paths[i]);
+        let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                                       MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                                       |bd, i| &bd.move_data().move_paths[i]);
+
+        let mut mbcx = MirBorrowckCtxt {
+            tcx: tcx,
+            mir: mir,
+            node_id: id,
+            move_data: &mdpe.move_data,
+            param_env: param_env,
+            fake_infer_ctxt: &_infcx,
+        };
+
+        let mut state = InProgress::new(flow_borrows,
+                                        flow_inits,
+                                        flow_uninits);
+
+        mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
+    });
+
+    debug!("mir_borrowck done");
+}
+
+#[allow(dead_code)]
+pub struct MirBorrowckCtxt<'c, 'b, 'a: 'b+'c, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    mir: &'b Mir<'gcx>,
+    node_id: ast::NodeId,
+    move_data: &'b MoveData<'gcx>,
+    param_env: ParamEnv<'tcx>,
+    fake_infer_ctxt: &'c InferCtxt<'c, 'gcx, 'tcx>,
+}
+
+// (forced to be `pub` due to its use as an associated type below.)
+pub struct InProgress<'b, 'tcx: 'b> {
+    borrows: FlowInProgress<Borrows<'b, 'tcx>>,
+    inits: FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>,
+    uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>,
+}
+
+struct FlowInProgress<BD> where BD: BitDenotation {
+    base_results: DataflowResults<BD>,
+    curr_state: IdxSetBuf<BD::Idx>,
+    stmt_gen: IdxSetBuf<BD::Idx>,
+    stmt_kill: IdxSetBuf<BD::Idx>,
+}
+
+// Check that:
+// 1. assignments are always made to mutable locations (FIXME: does that still really go here?)
+// 2. loans made in overlapping scopes do not conflict
+// 3. assignments do not affect things loaned out as immutable
+// 4. moves do not affect things loaned out in any way
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
+    for MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
+{
+    type FlowState = InProgress<'b, 'gcx>;
+
+    fn mir(&self) -> &'b Mir<'gcx> { self.mir }
+
+    fn reset_to_entry_of(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) {
+        flow_state.each_flow(|b| b.reset_to_entry_of(bb),
+                             |i| i.reset_to_entry_of(bb),
+                             |u| u.reset_to_entry_of(bb));
+    }
+
+    fn reconstruct_statement_effect(&mut self,
+                                    location: Location,
+                                    flow_state: &mut Self::FlowState) {
+        flow_state.each_flow(|b| b.reconstruct_statement_effect(location),
+                             |i| i.reconstruct_statement_effect(location),
+                             |u| u.reconstruct_statement_effect(location));
+    }
+
+    fn apply_local_effect(&mut self,
+                          _location: Location,
+                          flow_state: &mut Self::FlowState) {
+        flow_state.each_flow(|b| b.apply_local_effect(),
+                             |i| i.apply_local_effect(),
+                             |u| u.apply_local_effect());
+    }
+
+    fn reconstruct_terminator_effect(&mut self,
+                                     location: Location,
+                                     flow_state: &mut Self::FlowState) {
+        flow_state.each_flow(|b| b.reconstruct_terminator_effect(location),
+                             |i| i.reconstruct_terminator_effect(location),
+                             |u| u.reconstruct_terminator_effect(location));
+    }
+
+    fn visit_block_entry(&mut self,
+                         bb: BasicBlock,
+                         flow_state: &Self::FlowState) {
+        let summary = flow_state.summary();
+        debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, summary);
+    }
+
+    fn visit_statement_entry(&mut self,
+                             location: Location,
+                             stmt: &Statement<'gcx>,
+                             flow_state: &Self::FlowState) {
+        let summary = flow_state.summary();
+        debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {}", location, stmt, summary);
+        let span = stmt.source_info.span;
+        match stmt.kind {
+            StatementKind::Assign(ref lhs, ref rhs) => {
+                self.mutate_lvalue(ContextKind::AssignLhs.new(location),
+                                   (lhs, span), 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);
+            }
+            StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
+                for (o, output) in asm.outputs.iter().zip(outputs) {
+                    if o.is_indirect {
+                        self.consume_lvalue(ContextKind::InlineAsm.new(location),
+                                            Consume,
+                                            (output, span),
+                                            flow_state);
+                    } else {
+                        self.mutate_lvalue(ContextKind::InlineAsm.new(location),
+                                           (output, span),
+                                           if o.is_rw { WriteAndRead } else { JustWrite },
+                                           flow_state);
+                    }
+                }
+                for input in inputs {
+                    self.consume_operand(ContextKind::InlineAsm.new(location),
+                                         Consume,
+                                         (input, span), flow_state);
+                }
+            }
+            StatementKind::EndRegion(ref _rgn) => {
+                // ignored when consuming results (update to
+                // flow_state already handled).
+            }
+            StatementKind::Nop |
+            StatementKind::Validate(..) |
+            StatementKind::StorageLive(..) => {
+                // ignored by borrowck
+            }
+
+            StatementKind::StorageDead(ref lvalue) => {
+                // causes non-drop values to be dropped.
+                self.consume_lvalue(ContextKind::StorageDead.new(location),
+                                    ConsumeKind::Consume,
+                                    (lvalue, span),
+                                    flow_state)
+            }
+        }
+    }
+
+    fn visit_terminator_entry(&mut self,
+                              location: Location,
+                              term: &Terminator<'gcx>,
+                              flow_state: &Self::FlowState) {
+        let loc = location;
+        let summary = flow_state.summary();
+        debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {}", location, term, summary);
+        let span = term.source_info.span;
+        match term.kind {
+            TerminatorKind::SwitchInt { ref discr, switch_ty: _, values: _, targets: _ } => {
+                self.consume_operand(ContextKind::SwitchInt.new(loc),
+                                     Consume,
+                                     (discr, span), flow_state);
+            }
+            TerminatorKind::Drop { location: ref drop_lvalue, target: _, unwind: _ } => {
+                self.consume_lvalue(ContextKind::Drop.new(loc),
+                                    ConsumeKind::Drop,
+                                    (drop_lvalue, span), flow_state);
+            }
+            TerminatorKind::DropAndReplace { location: ref drop_lvalue,
+                                             value: ref new_value,
+                                             target: _,
+                                             unwind: _ } => {
+                self.mutate_lvalue(ContextKind::DropAndReplace.new(loc),
+                                   (drop_lvalue, span), JustWrite, flow_state);
+                self.consume_operand(ContextKind::DropAndReplace.new(loc),
+                                     ConsumeKind::Drop,
+                                     (new_value, span), flow_state);
+            }
+            TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
+                self.consume_operand(ContextKind::CallOperator.new(loc),
+                                     Consume,
+                                     (func, span), flow_state);
+                for arg in args {
+                    self.consume_operand(ContextKind::CallOperand.new(loc),
+                                         Consume,
+                                         (arg, span), flow_state);
+                }
+                if let Some((ref dest, _/*bb*/)) = *destination {
+                    self.mutate_lvalue(ContextKind::CallDest.new(loc),
+                                       (dest, span), JustWrite, flow_state);
+                }
+            }
+            TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+                self.consume_operand(ContextKind::Assert.new(loc),
+                                     Consume,
+                                     (cond, span), flow_state);
+                match *msg {
+                    AssertMessage::BoundsCheck { ref len, ref index } => {
+                        self.consume_operand(ContextKind::Assert.new(loc),
+                                             Consume,
+                                             (len, span), flow_state);
+                        self.consume_operand(ContextKind::Assert.new(loc),
+                                             Consume,
+                                             (index, span), flow_state);
+                    }
+                    AssertMessage::Math(_/*const_math_err*/) => {}
+                }
+            }
+
+            TerminatorKind::Goto { target: _ } |
+            TerminatorKind::Resume |
+            TerminatorKind::Return |
+            TerminatorKind::Unreachable => {
+                // no data used, thus irrelevant to borrowck
+            }
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum MutateMode { JustWrite, WriteAndRead }
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ConsumeKind { Drop, Consume }
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum Control { Continue, Break }
+
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
+    fn mutate_lvalue(&mut self,
+                     context: Context,
+                     lvalue_span: (&Lvalue<'gcx>, Span),
+                     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);
+            }
+            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
+                                        });
+
+        // check for reassignments to immutable local variables
+        self.check_if_reassignment_to_immutable_state(context, lvalue_span, flow_state);
+    }
+
+    fn consume_rvalue(&mut self,
+                      context: Context,
+                      (rvalue, span): (&Rvalue<'gcx>, Span),
+                      location: Location,
+                      flow_state: &InProgress<'b, 'gcx>) {
+        match *rvalue {
+            Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => {
+                self.borrow(context, location, bk, (lvalue, span), flow_state)
+            }
+
+            Rvalue::Use(ref operand) |
+            Rvalue::Repeat(ref operand, _) |
+            Rvalue::UnaryOp(_/*un_op*/, ref operand) |
+            Rvalue::Cast(_/*cast_kind*/, ref operand, _/*ty*/) => {
+                self.consume_operand(context, Consume, (operand, span), flow_state)
+            }
+
+            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);
+            }
+
+            Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) |
+            Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => {
+                self.consume_operand(context, Consume, (operand1, span), flow_state);
+                self.consume_operand(context, Consume, (operand2, span), flow_state);
+            }
+
+            Rvalue::NullaryOp(_op, _ty) => {
+                // nullary ops take no dynamic input; no borrowck effect.
+                //
+                // FIXME: is above actually true? Do we want to track
+                // the fact that uninitialized data can be created via
+                // `NullOp::Box`?
+            }
+
+            Rvalue::Aggregate(ref _aggregate_kind, ref operands) => {
+                for operand in operands {
+                    self.consume_operand(context, Consume, (operand, span), flow_state);
+                }
+            }
+        }
+    }
+
+    fn consume_operand(&mut self,
+                       context: Context,
+                       consume_via_drop: ConsumeKind,
+                       (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::Constant(_) => {}
+        }
+    }
+
+    fn consume_lvalue(&mut self,
+                      context: Context,
+                      consume_via_drop: ConsumeKind,
+                      lvalue_span: (&Lvalue<'gcx>, Span),
+                      flow_state: &InProgress<'b, 'gcx>) {
+        let lvalue = lvalue_span.0;
+        let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
+        let moves_by_default =
+            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
+                    }
+                });
+        } 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
+                    }
+                });
+        }
+
+        // Finally, check if path was already moved.
+        match consume_via_drop {
+            ConsumeKind::Drop => {
+                // If path is merely being dropped, then we'll already
+                // check the drop flag to see if it is moved (thus we
+                // skip this check in that case).
+            }
+            ConsumeKind::Consume => {
+                self.check_if_path_is_moved(context, 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> {
+    fn check_if_reassignment_to_immutable_state(&mut self,
+                                                context: Context,
+                                                (lvalue, span): (&Lvalue<'gcx>, Span),
+                                                flow_state: &InProgress<'b, 'gcx>) {
+        let move_data = flow_state.inits.base_results.operator().move_data();
+
+        // determine if this path has a non-mut owner (and thus needs checking).
+        let mut l = lvalue;
+        loop {
+            match *l {
+                Lvalue::Projection(ref proj) => {
+                    l = &proj.base;
+                    continue;
+                }
+                Lvalue::Local(local) => {
+                    match self.mir.local_decls[local].mutability {
+                        Mutability::Not => break, // needs check
+                        Mutability::Mut => return,
+                    }
+                }
+                Lvalue::Static(_) => {
+                    // mutation of non-mut static is always illegal,
+                    // independent of dataflow.
+                    self.report_assignment_to_static(context, (lvalue, span));
+                    return;
+                }
+            }
+        }
+
+        if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) {
+            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));
+            }
+        }
+    }
+
+    fn check_if_path_is_moved(&mut self,
+                              context: Context,
+                              lvalue_span: (&Lvalue<'gcx>, Span),
+                              flow_state: &InProgress<'b, 'gcx>) {
+        // FIXME: analogous code in check_loans first maps `lvalue` to
+        // its base_path ... but is that what we want here?
+        let lvalue = self.base_path(lvalue_span.0);
+
+        let maybe_uninits = &flow_state.uninits;
+        let move_data = maybe_uninits.base_results.operator().move_data();
+        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);
+            } else {
+                // sanity check: initialized on *some* path, right?
+                assert!(flow_state.inits.curr_state.contains(&mpi));
+            }
+        }
+    }
+
+    fn move_path_for_lvalue(&mut self,
+                            _context: Context,
+                            move_data: &MoveData<'gcx>,
+                            lvalue: &Lvalue<'gcx>)
+                            -> Option<MovePathIndex>
+    {
+        // If returns None, then there is no move path corresponding
+        // to a direct owner of `lvalue` (which means there is nothing
+        // that borrowck tracks for its analysis).
+
+        match move_data.rev_lookup.find(lvalue) {
+            LookupResult::Parent(_) => None,
+            LookupResult::Exact(mpi) => Some(mpi),
+        }
+    }
+
+    fn check_if_assigned_path_is_moved(&mut self,
+                                       context: Context,
+                                       (lvalue, span): (&Lvalue<'gcx>, Span),
+                                       flow_state: &InProgress<'b, 'gcx>) {
+        // recur down lvalue; dispatch to check_if_path_is_moved when necessary
+        let mut lvalue = lvalue;
+        loop {
+            match *lvalue {
+                Lvalue::Local(_) | Lvalue::Static(_) => {
+                    // assigning to `x` does not require `x` be initialized.
+                    break;
+                }
+                Lvalue::Projection(ref proj) => {
+                    let Projection { ref base, ref elem } = **proj;
+                    match *elem {
+                        ProjectionElem::Deref |
+                        // assigning to *P requires `P` initialized.
+                        ProjectionElem::Index(_/*operand*/) |
+                        ProjectionElem::ConstantIndex { .. } |
+                        // assigning to P[i] requires `P` initialized.
+                        ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
+                        // assigning to (P->variant) is okay if assigning to `P` is okay
+                        //
+                        // FIXME: is this true even if P is a adt with a dtor?
+                        { }
+
+                        ProjectionElem::Subslice { .. } => {
+                            panic!("we dont allow assignments to subslices, context: {:?}",
+                                   context);
+                        }
+
+                        ProjectionElem::Field(..) => {
+                            // if type of `P` has a dtor, then
+                            // assigning to `P.f` requires `P` itself
+                            // be already initialized
+                            let tcx = self.tcx;
+                            match base.ty(self.mir, tcx).to_ty(tcx).sty {
+                                ty::TyAdt(def, _) if def.has_dtor(tcx) => {
+
+                                    // FIXME: analogous code in
+                                    // check_loans.rs first maps
+                                    // `base` to its base_path.
+
+                                    self.check_if_path_is_moved(context,
+                                                                (base, span), flow_state);
+
+                                    // (base initialized; no need to
+                                    // recur further)
+                                    break;
+                                }
+                                _ => {}
+                            }
+                        }
+                    }
+
+                    lvalue = base;
+                    continue;
+                }
+            }
+        }
+    }
+
+    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
+        // CodeExtent)
+        //
+        // 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>,
+                                     flow_state: &InProgress<'b, 'gcx>,
+                                     mut op: F)
+        where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>) -> Control
+    {
+        // FIXME: analogous code in check_loans first maps `lvalue` to
+        // its base_path.
+
+        let domain = flow_state.borrows.base_results.operator();
+        let data = domain.borrows();
+
+        // 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.
+            let borrowed = &data[i];
+            for restricted in self.restrictions(&borrowed.lvalue) {
+                if restricted == lvalue {
+                    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 {
+                    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 rustc::hir;
+    use rustc::ty::{self, TyCtxt};
+    use rustc::mir::{Lvalue, Mir, Operand, ProjectionElem};
+
+    pub(super) struct Restrictions<'c, 'tcx: 'c> {
+        mir: &'c Mir<'tcx>,
+        tcx: TyCtxt<'c, 'tcx, 'tcx>,
+        lvalue_stack: Vec<&'c Lvalue<'tcx>>,
+    }
+
+    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
+        {
+            let lvalue_stack = if self.has_restrictions(lvalue) { vec![lvalue] } else { vec![] };
+            Restrictions { lvalue_stack: lvalue_stack, mir: self.mir, tcx: self.tcx }
+        }
+
+        fn has_restrictions(&self, lvalue: &Lvalue<'gcx>) -> bool {
+            let mut cursor = lvalue;
+            loop {
+                let proj = match *cursor {
+                    Lvalue::Local(_) => return true,
+                    Lvalue::Static(_) => return false,
+                    Lvalue::Projection(ref proj) => proj,
+                };
+                match proj.elem {
+                    ProjectionElem::Index(..) |
+                    ProjectionElem::ConstantIndex { .. } |
+                    ProjectionElem::Downcast(..) |
+                    ProjectionElem::Subslice { .. } |
+                    ProjectionElem::Field(_/*field*/, _/*ty*/) => {
+                        cursor = &proj.base;
+                        continue;
+                    }
+                    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.");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    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,
+                };
+
+                // `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(Operand::Constant(..)) => {
+                            cursor = &proj.base;
+                            continue 'cursor;
+                        }
+                        ProjectionElem::Index(Operand::Consume(ref index)) => {
+                            self.lvalue_stack.push(index); // FIXME: did old borrowck do this?
+                            cursor = &proj.base;
+                            continue 'cursor;
+                        }
+                        ProjectionElem::Deref => {
+                            // (handled below)
+                        }
+                    }
+
+                    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
+                        }
+
+                        // 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
+                        }
+
+                        _ => panic!("unknown type fed to Projection Deref."),
+                    }
+                }
+            }
+        }
+    }
+}
+
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
+    fn report_use_of_moved(&mut self,
+                           _context: Context,
+                           (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();
+    }
+
+    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();
+    }
+
+    fn report_use_while_mutably_borrowed(&mut self,
+                                         _context: Context,
+                                         (lvalue, span): (&Lvalue, Span)) {
+        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"
+        err.emit();
+    }
+
+    fn report_conflicting_borrow(&mut self,
+                                 _context: Context,
+                                 (lvalue, span): (&Lvalue, Span),
+                                 loan1: &BorrowData,
+                                 loan2: &BorrowData) {
+        // FIXME: obviously falsifiable. Generalize for non-eq lvalues later.
+        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") {
+            (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
+            (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) |
+            (BorrowKind::Mut, _, lft, BorrowKind::Mut, _, 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),
+            // 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)) {
+        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.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_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) {
+        let mut err = self.tcx.cannot_assign_static(
+            span, &self.describe_lvalue(lvalue), Origin::Mir);
+        // FIXME: add span labels for borrow and assignment points
+        err.emit();
+    }
+}
+
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
+    // End-user visible description of `lvalue`
+    fn describe_lvalue(&self, lvalue: &Lvalue) -> String {
+        let mut buf = String::new();
+        self.append_lvalue_to_string(lvalue, &mut buf);
+        buf
+    }
+
+    // Appends end-user visible description of `lvalue` to `buf`.
+    fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String) {
+        match *lvalue {
+            Lvalue::Local(local) => {
+                let local = &self.mir.local_decls[local];
+                match local.name {
+                    Some(name) => buf.push_str(&format!("{}", name)),
+                    None => buf.push_str("_"),
+                }
+            }
+            Lvalue::Static(ref static_) => {
+                buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
+            }
+            Lvalue::Projection(ref proj) => {
+                let (prefix, suffix, index_operand) = match proj.elem {
+                    ProjectionElem::Deref =>
+                        ("(*", format!(")"), None),
+                    ProjectionElem::Downcast(..) =>
+                        ("",   format!(""), None), // (dont emit downcast info)
+                    ProjectionElem::Field(field, _ty) =>
+                        ("",   format!(".{}", field.index()), None),
+                    ProjectionElem::Index(ref index) =>
+                        ("",   format!(""), Some(index)),
+                    ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
+                        ("",   format!("[{} of {}]", offset, min_length), None),
+                    ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
+                        ("",   format!("[-{} of {}]", offset, min_length), None),
+                    ProjectionElem::Subslice { from, to: 0 } =>
+                        ("",   format!("[{}:]", from), None),
+                    ProjectionElem::Subslice { from: 0, to } =>
+                        ("",   format!("[:-{}]", to), None),
+                    ProjectionElem::Subslice { from, to } =>
+                        ("",   format!("[{}:-{}]", from, to), None),
+                };
+                buf.push_str(prefix);
+                self.append_lvalue_to_string(&proj.base, buf);
+                if let Some(index) = index_operand {
+                    buf.push_str("[");
+                    self.append_operand_to_string(index, buf);
+                    buf.push_str("]");
+                } else {
+                    buf.push_str(&suffix);
+                }
+
+            }
+        }
+    }
+
+    fn append_operand_to_string(&self, operand: &Operand, buf: &mut String) {
+        match *operand {
+            Operand::Consume(ref lvalue) => {
+                self.append_lvalue_to_string(lvalue, buf);
+            }
+            Operand::Constant(ref constant) => {
+                buf.push_str(&format!("{:?}", constant));
+            }
+        }
+    }
+}
+
+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;
+    }
+
+    // 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
+    // treating Box specially (e.g. when/if DerefMove is added...)
+
+    fn base_path<'d>(&self, lvalue: &'d Lvalue<'gcx>) -> &'d Lvalue<'gcx> {
+        //! Returns the base of the leftmost (deepest) dereference of an
+        //! Box in `lvalue`. If there is no dereference of an Box
+        //! in `lvalue`, then it just returns `lvalue` itself.
+
+        let mut cursor = lvalue;
+        let mut deepest = lvalue;
+        loop {
+            let proj = match *cursor {
+                Lvalue::Local(..) | Lvalue::Static(..) => return deepest,
+                Lvalue::Projection(ref proj) => proj,
+            };
+            if proj.elem == ProjectionElem::Deref &&
+                lvalue.ty(self.mir, self.tcx).to_ty(self.tcx).is_box()
+            {
+                deepest = &proj.base;
+            }
+            cursor = &proj.base;
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+struct Context {
+    kind: ContextKind,
+    loc: Location,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum ContextKind {
+    AssignLhs,
+    AssignRhs,
+    SetDiscrim,
+    InlineAsm,
+    SwitchInt,
+    Drop,
+    DropAndReplace,
+    CallOperator,
+    CallOperand,
+    CallDest,
+    Assert,
+    StorageDead,
+}
+
+impl ContextKind {
+    fn new(self, loc: Location) -> Context { Context { kind: self, loc: loc } }
+}
+
+impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> {
+    pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'tcx>>,
+                      inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
+                      uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>)
+                      -> Self {
+        InProgress {
+            borrows: FlowInProgress::new(borrows),
+            inits: FlowInProgress::new(inits),
+            uninits: FlowInProgress::new(uninits),
+        }
+    }
+
+    fn each_flow<XB, XI, XU>(&mut self,
+                             mut xform_borrows: XB,
+                             mut xform_inits: XI,
+                             mut xform_uninits: XU) where
+        XB: FnMut(&mut FlowInProgress<Borrows<'b, 'tcx>>),
+        XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>),
+        XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>),
+    {
+        xform_borrows(&mut self.borrows);
+        xform_inits(&mut self.inits);
+        xform_uninits(&mut self.uninits);
+    }
+
+    fn summary(&self) -> String {
+        let mut s = String::new();
+
+        s.push_str("borrows in effect: [");
+        let mut saw_one = false;
+        self.borrows.each_state_bit(|borrow| {
+            if saw_one { s.push_str(", "); };
+            saw_one = true;
+            let borrow_data = &self.borrows.base_results.operator().borrows()[borrow];
+            s.push_str(&format!("{}", borrow_data));
+        });
+        s.push_str("] ");
+
+        s.push_str("borrows generated: [");
+        let mut saw_one = false;
+        self.borrows.each_gen_bit(|borrow| {
+            if saw_one { s.push_str(", "); };
+            saw_one = true;
+            let borrow_data = &self.borrows.base_results.operator().borrows()[borrow];
+            s.push_str(&format!("{}", borrow_data));
+        });
+        s.push_str("] ");
+
+        s.push_str("inits: [");
+        let mut saw_one = false;
+        self.inits.each_state_bit(|mpi_init| {
+            if saw_one { s.push_str(", "); };
+            saw_one = true;
+            let move_path =
+                &self.inits.base_results.operator().move_data().move_paths[mpi_init];
+            s.push_str(&format!("{}", move_path));
+        });
+        s.push_str("] ");
+
+        s.push_str("uninits: [");
+        let mut saw_one = false;
+        self.uninits.each_state_bit(|mpi_uninit| {
+            if saw_one { s.push_str(", "); };
+            saw_one = true;
+            let move_path =
+                &self.uninits.base_results.operator().move_data().move_paths[mpi_uninit];
+            s.push_str(&format!("{}", move_path));
+        });
+        s.push_str("]");
+
+        return s;
+    }
+}
+
+impl<BD> FlowInProgress<BD> where BD: BitDenotation {
+    fn each_state_bit<F>(&self, f: F) where F: FnMut(BD::Idx) {
+        self.curr_state.each_bit(self.base_results.operator().bits_per_block(), f)
+    }
+
+    fn each_gen_bit<F>(&self, f: F) where F: FnMut(BD::Idx) {
+        self.stmt_gen.each_bit(self.base_results.operator().bits_per_block(), f)
+    }
+
+    fn new(results: DataflowResults<BD>) -> Self {
+        let bits_per_block = results.sets().bits_per_block();
+        let curr_state = IdxSetBuf::new_empty(bits_per_block);
+        let stmt_gen = IdxSetBuf::new_empty(bits_per_block);
+        let stmt_kill = IdxSetBuf::new_empty(bits_per_block);
+        FlowInProgress {
+            base_results: results,
+            curr_state: curr_state,
+            stmt_gen: stmt_gen,
+            stmt_kill: stmt_kill,
+        }
+    }
+
+    fn reset_to_entry_of(&mut self, bb: BasicBlock) {
+        (*self.curr_state).clone_from(self.base_results.sets().on_entry_set_for(bb.index()));
+    }
+
+    fn reconstruct_statement_effect(&mut self, loc: Location) {
+        self.stmt_gen.reset_to_empty();
+        self.stmt_kill.reset_to_empty();
+        let mut ignored = IdxSetBuf::new_empty(0);
+        let mut sets = BlockSets {
+            on_entry: &mut ignored, gen_set: &mut self.stmt_gen, kill_set: &mut self.stmt_kill,
+        };
+        self.base_results.operator().statement_effect(&mut sets, loc);
+    }
+
+    fn reconstruct_terminator_effect(&mut self, loc: Location) {
+        self.stmt_gen.reset_to_empty();
+        self.stmt_kill.reset_to_empty();
+        let mut ignored = IdxSetBuf::new_empty(0);
+        let mut sets = BlockSets {
+            on_entry: &mut ignored, gen_set: &mut self.stmt_gen, kill_set: &mut self.stmt_kill,
+        };
+        self.base_results.operator().terminator_effect(&mut sets, loc);
+    }
+
+    fn apply_local_effect(&mut self) {
+        self.curr_state.union(&self.stmt_gen);
+        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/cfg.rs b/src/librustc_mir/build/cfg.rs
index c20f8bde783..b390e2888f2 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir/build/cfg.rs
@@ -49,7 +49,7 @@ impl<'tcx> CFG<'tcx> {
                            source_info: SourceInfo,
                            extent: CodeExtent) {
         self.push(block, Statement {
-            source_info: source_info,
+            source_info,
             kind: StatementKind::EndRegion(extent),
         });
     }
@@ -60,7 +60,7 @@ impl<'tcx> CFG<'tcx> {
                        lvalue: &Lvalue<'tcx>,
                        rvalue: Rvalue<'tcx>) {
         self.push(block, Statement {
-            source_info: source_info,
+            source_info,
             kind: StatementKind::Assign(lvalue.clone(), rvalue)
         });
     }
@@ -93,8 +93,8 @@ impl<'tcx> CFG<'tcx> {
                       block,
                       self.block_data(block));
         self.block_data_mut(block).terminator = Some(Terminator {
-            source_info: source_info,
-            kind: kind,
+            source_info,
+            kind,
         });
     }
 }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index a625f4b0458..c74378bdadc 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 if let Some(scope) = scope {
                     // schedule a shallow free of that memory, lest we unwind:
                     this.cfg.push(block, Statement {
-                        source_info: source_info,
+                        source_info,
                         kind: StatementKind::StorageLive(result.clone())
                     });
                     this.schedule_drop(expr_span, scope, &result, value.ty);
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 9be306d2848..4f248ddb0e2 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         if !expr_ty.is_never() && temp_lifetime.is_some() {
             this.cfg.push(block, Statement {
-                source_info: source_info,
+                source_info,
                 kind: StatementKind::StorageLive(temp.clone())
             });
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 7ae5d6b0ec1..576b1059e59 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -240,8 +240,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     let cleanup = this.diverge_cleanup();
                     this.cfg.terminate(block, source_info, TerminatorKind::Call {
                         func: fun,
-                        args: args,
-                        cleanup: cleanup,
+                        args,
+                        cleanup,
                         destination: if diverges {
                             None
                         } else {
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs
index 3120ac21908..0da722f72a1 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir/build/expr/stmt.rs
@@ -127,11 +127,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     unpack!(block = this.as_local_operand(block, input))
                 }).collect();
                 this.cfg.push(block, Statement {
-                    source_info: source_info,
+                    source_info,
                     kind: StatementKind::InlineAsm {
                         asm: box asm.clone(),
-                        outputs: outputs,
-                        inputs: inputs
+                        outputs,
+                        inputs,
                     },
                 });
                 block.unit()
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index c0b54ce2a84..78805ba87ec 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -69,8 +69,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         span: pattern.span,
                         match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
                         bindings: vec![],
-                        guard: guard,
-                        arm_index: arm_index,
+                        guard,
+                        arm_index,
                     }
                 })
                 .collect();
@@ -179,7 +179,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 var_scope = Some(this.new_visibility_scope(scope_span));
             }
             let source_info = SourceInfo {
-                span: span,
+                span,
                 scope: var_scope.unwrap()
             };
             this.declare_binding(source_info, mutability, name, var, ty);
@@ -193,7 +193,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let local_id = self.var_indices[&var];
         let source_info = self.source_info(span);
         self.cfg.push(block, Statement {
-            source_info: source_info,
+            source_info,
             kind: StatementKind::StorageLive(Lvalue::Local(local_id))
         });
         Lvalue::Local(local_id)
@@ -708,10 +708,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                var_id, name, var_ty, source_info);
 
         let var = self.local_decls.push(LocalDecl::<'tcx> {
-            mutability: mutability,
+            mutability,
             ty: var_ty.clone(),
             name: Some(name),
-            source_info: source_info,
+            source_info,
             is_user_variable: true,
         });
         self.var_indices.insert(var_id, var);
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index efddee2c933..6e3eef57352 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -71,8 +71,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
             PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
                 candidate.bindings.push(Binding {
-                    name: name,
-                    mutability: mutability,
+                    name,
+                    mutability,
                     span: match_pair.pattern.span,
                     source: match_pair.lvalue.clone(),
                     var_id: var,
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 28386fa598c..dc15163ecc1 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     discr: Operand::Consume(discr),
                     switch_ty: discr_ty,
                     values: From::from(values),
-                    targets: targets
+                    targets,
                 });
                 target_blocks
             }
@@ -249,9 +249,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     ).collect();
                     (targets.clone(), TerminatorKind::SwitchInt {
                         discr: Operand::Consume(lvalue.clone()),
-                        switch_ty: switch_ty,
+                        switch_ty,
                         values: From::from(values),
-                        targets: targets,
+                        targets,
                     })
                 };
                 self.cfg.terminate(block, source_info, terminator);
@@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         }),
                         args: vec![val, expect],
                         destination: Some((eq_result.clone(), eq_block)),
-                        cleanup: cleanup,
+                        cleanup,
                     });
 
                     // check the result
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs
index a013875b311..3e303865ac4 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir/build/matches/util.rs
@@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                   .map(|(idx, subpattern)| {
                       let elem = ProjectionElem::ConstantIndex {
                           offset: idx as u32,
-                          min_length: min_length,
+                          min_length,
                           from_end: false,
                       };
                       let lvalue = lvalue.clone().elem(elem);
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                   .map(|(idx, subpattern)| {
                       let elem = ProjectionElem::ConstantIndex {
                           offset: (idx+1) as u32,
-                          min_length: min_length,
+                          min_length,
                           from_end: true,
                       };
                       let lvalue = lvalue.clone().elem(elem);
@@ -80,8 +80,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
     pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
         MatchPair {
-            lvalue: lvalue,
-            pattern: pattern,
+            lvalue,
+            pattern,
             slice_len_checked: false,
         }
     }
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 6c93e073de6..0e4aac42991 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -41,9 +41,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                            literal: Literal<'tcx>)
                            -> Operand<'tcx> {
         let constant = box Constant {
-            span: span,
-            ty: ty,
-            literal: literal,
+            span,
+            ty,
+            literal,
         };
         Operand::Constant(constant)
     }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 14392ae70e4..d7a295a1c3a 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -121,7 +121,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
         // Convert the Mir to global types.
         let mut globalizer = GlobalizeMir {
-            tcx: tcx,
+            tcx,
             span: mir.span
         };
         globalizer.visit_mir(&mut mir);
@@ -179,7 +179,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // Convert the Mir to global types.
             let tcx = infcx.tcx.global_tcx();
             let mut globalizer = GlobalizeMir {
-                tcx: tcx,
+                tcx,
                 span: mir.span
             };
             globalizer.visit_mir(&mut mir);
@@ -380,9 +380,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
             };
             let mut decl = UpvarDecl {
                 debug_name: keywords::Invalid.name(),
-                by_ref: by_ref
+                by_ref,
             };
-            if let Some(hir::map::NodeLocal(pat)) = tcx.hir.find(var_node_id) {
+            if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_node_id) {
                 if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
                     decl.debug_name = ident.node;
                 }
@@ -437,10 +437,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
            return_ty: Ty<'tcx>)
            -> Builder<'a, 'gcx, 'tcx> {
         let mut builder = Builder {
-            hir: hir,
+            hir,
             cfg: CFG { basic_blocks: IndexVec::new() },
             fn_span: span,
-            arg_count: arg_count,
+            arg_count,
             scopes: vec![],
             visibility_scopes: IndexVec::new(),
             visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
@@ -500,12 +500,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
             self.local_decls.push(LocalDecl {
                 mutability: Mutability::Not,
-                ty: ty,
+                ty,
                 source_info: SourceInfo {
                     scope: ARGUMENT_VISIBILITY_SCOPE,
                     span: pattern.map_or(self.fn_span, |pat| pat.span)
                 },
-                name: name,
+                name,
                 is_user_variable: false,
             });
         }
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index ce64f88d18e..c36da9410f3 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -89,7 +89,7 @@ should go to.
 
 use build::{BlockAnd, BlockAndExtension, Builder, CFG};
 use rustc::middle::region::CodeExtent;
-use rustc::ty::{Ty, TyCtxt};
+use rustc::ty::Ty;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 use syntax_pos::{Span};
@@ -213,7 +213,7 @@ impl<'tcx> Scope<'tcx> {
     /// Given a span and this scope's visibility scope, make a SourceInfo.
     fn source_info(&self, span: Span) -> SourceInfo {
         SourceInfo {
-            span: span,
+            span,
             scope: self.visibility_scope
         }
     }
@@ -235,10 +235,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     {
         let extent = self.topmost_scope();
         let scope = BreakableScope {
-            extent: extent,
+            extent,
             continue_block: loop_block,
-            break_block: break_block,
-            break_destination: break_destination,
+            break_block,
+            break_destination,
         };
         self.breakable_scopes.push(scope);
         let res = f(self);
@@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let parent = self.visibility_scope;
         let scope = VisibilityScope::new(self.visibility_scopes.len());
         self.visibility_scopes.push(VisibilityScopeData {
-            span: span,
+            span,
             parent_scope: Some(parent),
         });
         scope
@@ -411,7 +411,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// Given a span and the current visibility scope, make a SourceInfo.
     pub fn source_info(&self, span: Span) -> SourceInfo {
         SourceInfo {
-            span: span,
+            span,
             scope: self.visibility_scope
         }
     }
@@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         }
         assert!(!self.scopes.is_empty()); // or `any` above would be false
 
-        let Builder { ref mut hir, ref mut cfg, ref mut scopes,
+        let Builder { ref mut cfg, ref mut scopes,
                       ref mut cached_resume_block, .. } = *self;
 
         // Build up the drops in **reverse** order. The end result will
@@ -599,8 +599,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         };
 
         for scope in scopes.iter_mut() {
-            target = build_diverge_scope(
-                hir.tcx(), cfg, scope.extent_span, scope, target);
+            target = build_diverge_scope(cfg, scope.extent_span, scope, target);
         }
         Some(target)
     }
@@ -619,7 +618,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let diverge_target = self.diverge_cleanup();
         self.cfg.terminate(block, source_info,
                            TerminatorKind::Drop {
-                               location: location,
+                               location,
                                target: next_target,
                                unwind: diverge_target,
                            });
@@ -637,8 +636,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let diverge_target = self.diverge_cleanup();
         self.cfg.terminate(block, source_info,
                            TerminatorKind::DropAndReplace {
-                               location: location,
-                               value: value,
+                               location,
+                               value,
                                target: next_target,
                                unwind: diverge_target,
                            });
@@ -661,11 +660,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         self.cfg.terminate(block, source_info,
                            TerminatorKind::Assert {
-                               cond: cond,
-                               expected: expected,
-                               msg: msg,
+                               cond,
+                               expected,
+                               msg,
                                target: success_block,
-                               cleanup: cleanup
+                               cleanup,
                            });
 
         success_block
@@ -716,7 +715,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
         match drop_data.location {
             Lvalue::Local(index) if index.index() > arg_count => {
                 cfg.push(block, Statement {
-                    source_info: source_info,
+                    source_info,
                     kind: StatementKind::StorageDead(drop_data.location.clone())
                 });
             }
@@ -726,8 +725,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
     block.unit()
 }
 
-fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                       cfg: &mut CFG<'tcx>,
+fn build_diverge_scope<'a, 'gcx, 'tcx>(cfg: &mut CFG<'tcx>,
                                        span: Span,
                                        scope: &mut Scope<'tcx>,
                                        mut target: BasicBlock)
@@ -748,7 +746,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
     let visibility_scope = scope.visibility_scope;
     let source_info = |span| SourceInfo {
-        span: span,
+        span,
         scope: visibility_scope
     };
 
@@ -776,7 +774,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
             cfg.terminate(block, source_info(drop_data.span),
                           TerminatorKind::Drop {
                               location: drop_data.location.clone(),
-                              target: target,
+                              target,
                               unwind: None
                           });
             *cached_block = Some(block);
diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index 890fe3c091a..bd41bce67da 100644
--- a/src/librustc_mir/dataflow/drop_flag_effects.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -8,84 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::ast::{self, MetaItem};
 use syntax_pos::DUMMY_SP;
 
-
-use rustc::mir::{self, Mir, BasicBlock, Location};
-use rustc::session::Session;
+use rustc::mir::{self, Mir, Location};
 use rustc::ty::{self, TyCtxt};
 use util::elaborate_drops::DropFlagState;
-use rustc_data_structures::indexed_set::{IdxSet};
-
-use std::fmt;
 
-use super::{Dataflow, DataflowBuilder, DataflowAnalysis};
-use super::{BitDenotation, DataflowOperator, DataflowResults};
+use super::{MoveDataParamEnv};
 use super::indexes::MovePathIndex;
 use super::move_paths::{MoveData, LookupResult};
 
-pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
-    for attr in attrs {
-        if attr.check_name("rustc_mir") {
-            let items = attr.meta_item_list();
-            for item in items.iter().flat_map(|l| l.iter()) {
-                match item.meta_item() {
-                    Some(mi) if mi.check_name(name) => return Some(mi.clone()),
-                    _ => continue
-                }
-            }
-        }
-    }
-    return None;
-}
-
-pub struct MoveDataParamEnv<'tcx> {
-    pub(crate) move_data: MoveData<'tcx>,
-    pub(crate) param_env: ty::ParamEnv<'tcx>,
-}
-
-pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                mir: &Mir<'tcx>,
-                                node_id: ast::NodeId,
-                                attributes: &[ast::Attribute],
-                                dead_unwinds: &IdxSet<BasicBlock>,
-                                bd: BD,
-                                p: P)
-                                -> DataflowResults<BD>
-    where BD: BitDenotation<Idx=MovePathIndex> + DataflowOperator,
-          P: Fn(&BD, BD::Idx) -> &fmt::Debug
-{
-    let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
-        if let Some(item) = has_rustc_mir_with(attrs, name) {
-            if let Some(s) = item.value_str() {
-                return Some(s.to_string())
-            } else {
-                sess.span_err(
-                    item.span,
-                    &format!("{} attribute requires a path", item.name()));
-                return None;
-            }
-        }
-        return None;
-    };
-
-    let print_preflow_to =
-        name_found(tcx.sess, attributes, "borrowck_graphviz_preflow");
-    let print_postflow_to =
-        name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
-
-    let mut mbcx = DataflowBuilder {
-        node_id: node_id,
-        print_preflow_to: print_preflow_to,
-        print_postflow_to: print_postflow_to,
-        flow_state: DataflowAnalysis::new(tcx, mir, dead_unwinds, bd),
-    };
-
-    mbcx.dataflow(p);
-    mbcx.flow_state.results()
-}
-
 pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
                                         path: MovePathIndex,
                                         mut cond: F)
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index e6d77aa2686..7ff4fbcf199 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -13,7 +13,6 @@
 use syntax::ast::NodeId;
 use rustc::mir::{BasicBlock, Mir};
 use rustc_data_structures::bitslice::bits_to_string;
-use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
 use dot;
@@ -24,7 +23,6 @@ use std::fs::File;
 use std::io;
 use std::io::prelude::*;
 use std::marker::PhantomData;
-use std::mem;
 use std::path::Path;
 
 use util;
@@ -32,54 +30,6 @@ use util;
 use super::{BitDenotation, DataflowState};
 use super::DataflowBuilder;
 
-impl<O: BitDenotation> DataflowState<O> {
-    fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
-        where F: FnMut(O::Idx) {
-        //! Helper for iterating over the bits in a bitvector.
-
-        let bits_per_block = self.operator.bits_per_block();
-        let usize_bits: usize = mem::size_of::<usize>() * 8;
-
-        for (word_index, &word) in words.words().iter().enumerate() {
-            if word != 0 {
-                let base_index = word_index * usize_bits;
-                for offset in 0..usize_bits {
-                    let bit = 1 << offset;
-                    if (word & bit) != 0 {
-                        // NB: we round up the total number of bits
-                        // that we store in any given bit set so that
-                        // it is an even multiple of usize::BITS. This
-                        // means that there may be some stray bits at
-                        // the end that do not correspond to any
-                        // actual value; that's why we first check
-                        // that we are in range of bits_per_block.
-                        let bit_index = base_index + offset as usize;
-                        if bit_index >= bits_per_block {
-                            return;
-                        } else {
-                            f(O::Idx::new(bit_index));
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    pub fn interpret_set<'c, P>(&self,
-                                o: &'c O,
-                                words: &IdxSet<O::Idx>,
-                                render_idx: &P)
-                                -> Vec<&'c Debug>
-        where P: Fn(&O, O::Idx) -> &Debug
-    {
-        let mut v = Vec::new();
-        self.each_bit(words, |i| {
-            v.push(render_idx(o, i));
-        });
-        v
-    }
-}
-
 pub trait MirWithFlowState<'tcx> {
     type BD: BitDenotation;
     fn node_id(&self) -> NodeId;
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
new file mode 100644
index 00000000000..ab62342e607
--- /dev/null
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -0,0 +1,180 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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::mir::{self, Location, Mir};
+use rustc::mir::visit::Visitor;
+use rustc::ty::{Region, TyCtxt};
+use rustc::ty::RegionKind::ReScope;
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
+
+use rustc_data_structures::bitslice::{BitwiseOperator};
+use rustc_data_structures::indexed_set::{IdxSet};
+use rustc_data_structures::indexed_vec::{IndexVec};
+
+use dataflow::{BitDenotation, BlockSets, DataflowOperator};
+pub use dataflow::indexes::BorrowIndex;
+
+use std::fmt;
+
+// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
+// uniquely identified in the MIR by the `Location` of the assigment
+// statement in which it appears on the right hand side.
+pub struct Borrows<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
+    location_map: FxHashMap<Location, BorrowIndex>,
+    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+}
+
+// temporarily allow some dead fields: `kind` and `region` will be
+// needed by borrowck; `lvalue` will probably be a MovePathIndex when
+// that is extended to include borrowed data paths.
+#[allow(dead_code)]
+#[derive(Debug)]
+pub struct BorrowData<'tcx> {
+    pub(crate) location: Location,
+    pub(crate) kind: mir::BorrowKind,
+    pub(crate) region: Region<'tcx>,
+    pub(crate) lvalue: mir::Lvalue<'tcx>,
+}
+
+impl<'tcx> fmt::Display for BorrowData<'tcx> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        let kind = match self.kind {
+            mir::BorrowKind::Shared => "",
+            mir::BorrowKind::Unique => "uniq ",
+            mir::BorrowKind::Mut => "mut ",
+        };
+        let region = format!("{}", self.region);
+        let region = if region.len() > 0 { format!("{} ", region) } else { region };
+        write!(w, "&{}{}{:?}", region, kind, self.lvalue)
+    }
+}
+
+impl<'a, 'tcx> Borrows<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+        let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
+                                          location_map: FxHashMap(),
+                                          region_map: FxHashMap(), };
+        visitor.visit_mir(mir);
+        return Borrows { tcx: tcx,
+                         mir: mir,
+                         borrows: visitor.idx_vec,
+                         location_map: visitor.location_map,
+                         region_map: visitor.region_map, };
+
+        struct GatherBorrows<'tcx> {
+            idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
+            location_map: FxHashMap<Location, BorrowIndex>,
+            region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+        }
+        impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> {
+            fn visit_rvalue(&mut self,
+                            rvalue: &mir::Rvalue<'tcx>,
+                            location: mir::Location) {
+                if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue {
+                    let borrow = BorrowData {
+                        location: location, kind: kind, region: region, lvalue: lvalue.clone(),
+                    };
+                    let idx = self.idx_vec.push(borrow);
+                    self.location_map.insert(location, idx);
+                    let borrows = self.region_map.entry(region).or_insert(FxHashSet());
+                    borrows.insert(idx);
+                }
+            }
+        }
+    }
+
+    pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows }
+
+    pub fn location(&self, idx: BorrowIndex) -> &Location {
+        &self.borrows[idx].location
+    }
+}
+
+impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
+    type Idx = BorrowIndex;
+    fn name() -> &'static str { "borrows" }
+    fn bits_per_block(&self) -> usize {
+        self.borrows.len()
+    }
+    fn start_block_effect(&self, _sets: &mut BlockSets<BorrowIndex>)  {
+        // no borrows of code extents have been taken prior to
+        // function execution, so this method has no effect on
+        // `_sets`.
+    }
+    fn statement_effect(&self,
+                        sets: &mut BlockSets<BorrowIndex>,
+                        location: Location) {
+        let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
+            panic!("could not find block at location {:?}", location);
+        });
+        let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| {
+            panic!("could not find statement at location {:?}");
+        });
+        match stmt.kind {
+            mir::StatementKind::EndRegion(extent) => {
+                let borrow_indexes = self.region_map.get(&ReScope(extent)).unwrap_or_else(|| {
+                    panic!("could not find BorrowIndexs for code-extent {:?}", extent);
+                });
+
+                for idx in borrow_indexes { sets.kill(&idx); }
+            }
+
+            mir::StatementKind::Assign(_, ref rhs) => {
+                if let mir::Rvalue::Ref(region, _, _) = *rhs {
+                    let index = self.location_map.get(&location).unwrap_or_else(|| {
+                        panic!("could not find BorrowIndex for location {:?}", location);
+                    });
+                    assert!(self.region_map.get(region).unwrap_or_else(|| {
+                        panic!("could not find BorrowIndexs for region {:?}", region);
+                    }).contains(&index));
+                    sets.gen(&index);
+                }
+            }
+
+            mir::StatementKind::InlineAsm { .. } |
+            mir::StatementKind::SetDiscriminant { .. } |
+            mir::StatementKind::StorageLive(..) |
+            mir::StatementKind::StorageDead(..) |
+            mir::StatementKind::Validate(..) |
+            mir::StatementKind::Nop => {}
+
+        }
+    }
+    fn terminator_effect(&self,
+                         _sets: &mut BlockSets<BorrowIndex>,
+                         _location: Location) {
+        // no terminators start nor end code extents.
+    }
+
+    fn propagate_call_return(&self,
+                             _in_out: &mut IdxSet<BorrowIndex>,
+                             _call_bb: mir::BasicBlock,
+                             _dest_bb: mir::BasicBlock,
+                             _dest_lval: &mir::Lvalue) {
+        // there are no effects on the extents from method calls.
+    }
+}
+
+impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> {
+    #[inline]
+    fn join(&self, pred1: usize, pred2: usize) -> usize {
+        pred1 | pred2 // union effects of preds when computing borrows
+    }
+}
+
+impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> {
+    #[inline]
+    fn bottom_value() -> bool {
+        false // bottom = no Rvalue::Refs are active by default
+    }
+}
diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 41019799e41..a4421b216c3 100644
--- a/src/librustc_mir/dataflow/impls/mod.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -14,22 +14,22 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
 use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
-use rustc_data_structures::indexed_vec::Idx;
 
 use super::MoveDataParamEnv;
 use util::elaborate_drops::DropFlagState;
 
-use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
-use super::move_paths::LookupResult;
+use super::move_paths::{HasMoveData, MoveData, MovePathIndex};
 use super::{BitDenotation, BlockSets, DataflowOperator};
 
 use super::drop_flag_effects_for_function_entry;
 use super::drop_flag_effects_for_location;
 use super::on_lookup_result_bits;
 
+#[allow(dead_code)]
+pub(super) mod borrows;
+
 /// `MaybeInitializedLvals` tracks all l-values that might be
 /// initialized upon reaching a particular point in the control flow
 /// for a function.
@@ -201,40 +201,6 @@ impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
     fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
-/// `MovingOutStatements` tracks the statements that perform moves out
-/// of particular l-values. More precisely, it tracks whether the
-/// *effect* of such moves (namely, the uninitialization of the
-/// l-value in question) can reach some point in the control-flow of
-/// the function, or if that effect is "killed" by some intervening
-/// operation reinitializing that l-value.
-///
-/// The resulting dataflow is a more enriched version of
-/// `MaybeUninitializedLvals`. Both structures on their own only tell
-/// you if an l-value *might* be uninitialized at a given point in the
-/// control flow. But `MovingOutStatements` also includes the added
-/// data of *which* particular statement causing the deinitialization
-/// that the borrow checker's error message may need to report.
-#[allow(dead_code)]
-pub struct MovingOutStatements<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    mir: &'a Mir<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
-}
-
-impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               mir: &'a Mir<'tcx>,
-               mdpe: &'a MoveDataParamEnv<'tcx>)
-               -> Self
-    {
-        MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe }
-    }
-}
-
-impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
-}
-
 impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
     fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
                    state: DropFlagState)
@@ -287,24 +253,22 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
 
     fn statement_effect(&self,
                         sets: &mut BlockSets<MovePathIndex>,
-                        bb: mir::BasicBlock,
-                        idx: usize)
+                        location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: idx },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
                          sets: &mut BlockSets<MovePathIndex>,
-                         bb: mir::BasicBlock,
-                         statements_len: usize)
+                         location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: statements_len },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
@@ -344,24 +308,22 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
 
     fn statement_effect(&self,
                         sets: &mut BlockSets<MovePathIndex>,
-                        bb: mir::BasicBlock,
-                        idx: usize)
+                        location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: idx },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
                          sets: &mut BlockSets<MovePathIndex>,
-                         bb: mir::BasicBlock,
-                         statements_len: usize)
+                         location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: statements_len },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
@@ -400,24 +362,22 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
 
     fn statement_effect(&self,
                         sets: &mut BlockSets<MovePathIndex>,
-                        bb: mir::BasicBlock,
-                        idx: usize)
+                        location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: idx },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
                          sets: &mut BlockSets<MovePathIndex>,
-                         bb: mir::BasicBlock,
-                         statements_len: usize)
+                         location: Location)
     {
         drop_flag_effects_for_location(
             self.tcx, self.mir, self.mdpe,
-            Location { block: bb, statement_index: statements_len },
+            location,
             |path, s| Self::update_bits(sets, path, s)
         )
     }
@@ -435,125 +395,6 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
-    type Idx = MoveOutIndex;
-    fn name() -> &'static str { "moving_out" }
-    fn bits_per_block(&self) -> usize {
-        self.move_data().moves.len()
-    }
-
-    fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) {
-        // no move-statements have been executed prior to function
-        // execution, so this method has no effect on `_sets`.
-    }
-    fn statement_effect(&self,
-                        sets: &mut BlockSets<MoveOutIndex>,
-                        bb: mir::BasicBlock,
-                        idx: usize) {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
-        let stmt = &mir[bb].statements[idx];
-        let loc_map = &move_data.loc_map;
-        let path_map = &move_data.path_map;
-        let rev_lookup = &move_data.rev_lookup;
-
-        let loc = Location { block: bb, statement_index: idx };
-        debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}",
-               stmt, loc, &loc_map[loc]);
-        for move_index in &loc_map[loc] {
-            // Every path deinitialized by a *particular move*
-            // has corresponding bit, "gen'ed" (i.e. set)
-            // here, in dataflow vector
-            zero_to_one(sets.gen_set.words_mut(), *move_index);
-        }
-        let bits_per_block = self.bits_per_block();
-        match stmt.kind {
-            mir::StatementKind::SetDiscriminant { .. } => {
-                span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
-            }
-            mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
-                // assigning into this `lvalue` kills all
-                // MoveOuts from it, and *also* all MoveOuts
-                // for children and associated fragment sets.
-                match rvalue.initialization_state() {
-                    mir::tcx::RvalueInitializationState::Shallow => {
-                        if let LookupResult::Exact(mpi) = rev_lookup.find(lvalue) {
-                             for moi in &path_map[mpi] {
-                                 assert!(moi.index() < bits_per_block);
-                                 sets.kill_set.add(&moi);
-                             }
-                        }
-                    }
-                    mir::tcx::RvalueInitializationState::Deep => {
-                        on_lookup_result_bits(tcx,
-                                              mir,
-                                              move_data,
-                                              rev_lookup.find(lvalue),
-                                              |mpi| for moi in &path_map[mpi] {
-                                                  assert!(moi.index() < bits_per_block);
-                                                  sets.kill_set.add(&moi);
-                                              });
-                    }
-                }
-            }
-            mir::StatementKind::StorageLive(_) |
-            mir::StatementKind::StorageDead(_) |
-            mir::StatementKind::InlineAsm { .. } |
-            mir::StatementKind::EndRegion(_) |
-            mir::StatementKind::Validate(..) |
-            mir::StatementKind::Nop => {}
-        }
-    }
-
-    fn terminator_effect(&self,
-                         sets: &mut BlockSets<MoveOutIndex>,
-                         bb: mir::BasicBlock,
-                         statements_len: usize)
-    {
-        let (mir, move_data) = (self.mir, self.move_data());
-        let term = mir[bb].terminator();
-        let loc_map = &move_data.loc_map;
-        let loc = Location { block: bb, statement_index: statements_len };
-        debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
-               term, loc, &loc_map[loc]);
-        let bits_per_block = self.bits_per_block();
-        for move_index in &loc_map[loc] {
-            assert!(move_index.index() < bits_per_block);
-            zero_to_one(sets.gen_set.words_mut(), *move_index);
-        }
-    }
-
-    fn propagate_call_return(&self,
-                             in_out: &mut IdxSet<MoveOutIndex>,
-                             _call_bb: mir::BasicBlock,
-                             _dest_bb: mir::BasicBlock,
-                             dest_lval: &mir::Lvalue) {
-        let move_data = self.move_data();
-        let bits_per_block = self.bits_per_block();
-
-        let path_map = &move_data.path_map;
-        on_lookup_result_bits(self.tcx,
-                              self.mir,
-                              move_data,
-                              move_data.rev_lookup.find(dest_lval),
-                              |mpi| for moi in &path_map[mpi] {
-                                  assert!(moi.index() < bits_per_block);
-                                  in_out.remove(&moi);
-                              });
-    }
-}
-
-fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) {
-    let retval = bitvec.set_bit(move_index.index());
-    assert!(retval);
-}
-
-impl<'a, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'tcx> {
-    #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
-        pred1 | pred2 // moves from both preds are in scope
-    }
-}
-
 impl<'a, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'tcx> {
     #[inline]
     fn join(&self, pred1: usize, pred2: usize) -> usize {
@@ -585,13 +426,6 @@ impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> {
 // propagating, or you start at all-ones and then use Intersect as
 // your merge when propagating.
 
-impl<'a, 'tcx> DataflowOperator for MovingOutStatements<'a, 'tcx> {
-    #[inline]
-    fn bottom_value() -> bool {
-        false // bottom = no loans in scope by default
-    }
-}
-
 impl<'a, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'tcx> {
     #[inline]
     fn bottom_value() -> bool {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 7c0137b18c0..237795491b1 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -8,26 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::ast;
+use syntax::ast::{self, MetaItem};
 
 use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
 
-use rustc::ty::{TyCtxt};
-use rustc::mir::{self, Mir};
+use rustc::ty::{self, TyCtxt};
+use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
+use rustc::session::Session;
 
-use std::fmt::Debug;
+use std::fmt::{self, Debug};
 use std::io;
 use std::mem;
 use std::path::PathBuf;
 use std::usize;
 
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
-pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements};
-
+pub use self::impls::{DefinitelyInitializedLvals};
+pub use self::impls::borrows::{Borrows, BorrowData, BorrowIndex};
 pub(crate) use self::drop_flag_effects::*;
 
+use self::move_paths::MoveData;
+
 mod drop_flag_effects;
 mod graphviz;
 mod impls;
@@ -44,11 +47,22 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
 }
 
 pub trait Dataflow<BD: BitDenotation> {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
+    /// Sets up and runs the dataflow problem, using `p` to render results if
+    /// implementation so chooses.
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
+        let _ = p; // default implementation does not instrument process.
+        self.build_sets();
+        self.propagate();
+    }
+
+    /// Sets up the entry, gen, and kill sets for this instance of a dataflow problem.
+    fn build_sets(&mut self);
+
+    /// Finds a fixed-point solution to this instance of a dataflow problem.
+    fn propagate(&mut self);
 }
 
-impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD>
-    where BD: BitDenotation + DataflowOperator
+impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
 {
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
         self.flow_state.build_sets();
@@ -56,17 +70,79 @@ impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD>
         self.flow_state.propagate();
         self.post_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
     }
+
+    fn build_sets(&mut self) { self.flow_state.build_sets(); }
+    fn propagate(&mut self) { self.flow_state.propagate(); }
+}
+
+pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
+    for attr in attrs {
+        if attr.check_name("rustc_mir") {
+            let items = attr.meta_item_list();
+            for item in items.iter().flat_map(|l| l.iter()) {
+                match item.meta_item() {
+                    Some(mi) if mi.check_name(name) => return Some(mi.clone()),
+                    _ => continue
+                }
+            }
+        }
+    }
+    return None;
+}
+
+pub struct MoveDataParamEnv<'tcx> {
+    pub(crate) move_data: MoveData<'tcx>,
+    pub(crate) param_env: ty::ParamEnv<'tcx>,
+}
+
+pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                mir: &Mir<'tcx>,
+                                node_id: ast::NodeId,
+                                attributes: &[ast::Attribute],
+                                dead_unwinds: &IdxSet<BasicBlock>,
+                                bd: BD,
+                                p: P)
+                                -> DataflowResults<BD>
+    where BD: BitDenotation,
+          P: Fn(&BD, BD::Idx) -> &fmt::Debug
+{
+    let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
+        if let Some(item) = has_rustc_mir_with(attrs, name) {
+            if let Some(s) = item.value_str() {
+                return Some(s.to_string())
+            } else {
+                sess.span_err(
+                    item.span,
+                    &format!("{} attribute requires a path", item.name()));
+                return None;
+            }
+        }
+        return None;
+    };
+
+    let print_preflow_to =
+        name_found(tcx.sess, attributes, "borrowck_graphviz_preflow");
+    let print_postflow_to =
+        name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
+
+    let mut mbcx = DataflowBuilder {
+        node_id,
+        print_preflow_to,
+        print_postflow_to,
+        flow_state: DataflowAnalysis::new(tcx, mir, dead_unwinds, bd),
+    };
+
+    mbcx.dataflow(p);
+    mbcx.flow_state.results()
 }
 
-struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O>
-    where O: 'b + BitDenotation
+struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
     changed: bool,
 }
 
-impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD>
-    where BD: BitDenotation + DataflowOperator
+impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation
 {
     fn propagate(&mut self) {
         let mut temp = IdxSetBuf::new_empty(self.flow_state.sets.bits_per_block);
@@ -98,19 +174,19 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD>
 
             let sets = &mut self.flow_state.sets.for_block(bb.index());
             for j_stmt in 0..statements.len() {
-                self.flow_state.operator.statement_effect(sets, bb, j_stmt);
+                let location = Location { block: bb, statement_index: j_stmt };
+                self.flow_state.operator.statement_effect(sets, location);
             }
 
             if terminator.is_some() {
-                let stmts_len = statements.len();
-                self.flow_state.operator.terminator_effect(sets, bb, stmts_len);
+                let location = Location { block: bb, statement_index: statements.len() };
+                self.flow_state.operator.terminator_effect(sets, location);
             }
         }
     }
 }
 
-impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD>
-    where BD: BitDenotation + DataflowOperator
+impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation
 {
     fn reset(&mut self, bits: &mut IdxSet<BD::Idx>) {
         let e = if BD::bottom_value() {!0} else {0};
@@ -147,8 +223,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
     path
 }
 
-impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD>
-    where BD: BitDenotation
+impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
         where P: Fn(&BD, BD::Idx) -> &Debug
@@ -189,16 +264,101 @@ impl<E:Idx> Bits<E> {
     }
 }
 
-pub struct DataflowAnalysis<'a, 'tcx: 'a, O>
-    where O: BitDenotation
+/// DataflowResultsConsumer abstracts over walking the MIR with some
+/// already constructed dataflow results.
+///
+/// It abstracts over the FlowState and also completely hides the
+/// underlying flow analysis results, because it needs to handle cases
+/// where we are combining the results of *multiple* flow analyses
+/// (e.g. borrows + inits + uninits).
+pub trait DataflowResultsConsumer<'a, 'tcx: 'a> {
+    type FlowState;
+
+    // Observation Hooks: override (at least one of) these to get analysis feedback.
+    fn visit_block_entry(&mut self,
+                         _bb: BasicBlock,
+                         _flow_state: &Self::FlowState) {}
+
+    fn visit_statement_entry(&mut self,
+                             _loc: Location,
+                             _stmt: &Statement<'tcx>,
+                             _flow_state: &Self::FlowState) {}
+
+    fn visit_terminator_entry(&mut self,
+                              _loc: Location,
+                              _term: &Terminator<'tcx>,
+                              _flow_state: &Self::FlowState) {}
+
+    // Main entry point: this drives the processing of results.
+
+    fn analyze_results(&mut self, flow_uninit: &mut Self::FlowState) {
+        let flow = flow_uninit;
+        for bb in self.mir().basic_blocks().indices() {
+            self.reset_to_entry_of(bb, flow);
+            self.process_basic_block(bb, flow);
+        }
+    }
+
+    fn process_basic_block(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) {
+        let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } =
+            self.mir()[bb];
+        let mut location = Location { block: bb, statement_index: 0 };
+        for stmt in statements.iter() {
+            self.reconstruct_statement_effect(location, flow_state);
+            self.visit_statement_entry(location, stmt, flow_state);
+            self.apply_local_effect(location, flow_state);
+            location.statement_index += 1;
+        }
+
+        if let Some(ref term) = *terminator {
+            self.reconstruct_terminator_effect(location, flow_state);
+            self.visit_terminator_entry(location, term, flow_state);
+
+            // We don't need to apply the effect of the terminator,
+            // since we are only visiting dataflow state on control
+            // flow entry to the various nodes. (But we still need to
+            // reconstruct the effect, because the visit method might
+            // inspect it.)
+        }
+    }
+
+    // Delegated Hooks: Provide access to the MIR and process the flow state.
+
+    fn mir(&self) -> &'a Mir<'tcx>;
+
+    // reset the state bitvector to represent the entry to block `bb`.
+    fn reset_to_entry_of(&mut self,
+                         bb: BasicBlock,
+                         flow_state: &mut Self::FlowState);
+
+    // build gen + kill sets for statement at `loc`.
+    fn reconstruct_statement_effect(&mut self,
+                                    loc: Location,
+                                    flow_state: &mut Self::FlowState);
+
+    // build gen + kill sets for terminator for `loc`.
+    fn reconstruct_terminator_effect(&mut self,
+                                     loc: Location,
+                                     flow_state: &mut Self::FlowState);
+
+    // apply current gen + kill sets to `flow_state`.
+    //
+    // (`bb` and `stmt_idx` parameters can be ignored if desired by
+    // client. For the terminator, the `stmt_idx` will be the number
+    // of statements in the block.)
+    fn apply_local_effect(&mut self,
+                          loc: Location,
+                          flow_state: &mut Self::FlowState);
+}
+
+pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
 {
     flow_state: DataflowState<O>,
     dead_unwinds: &'a IdxSet<mir::BasicBlock>,
     mir: &'a Mir<'tcx>,
 }
 
-impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
-    where O: BitDenotation
+impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation
 {
     pub fn results(self) -> DataflowResults<O> {
         DataflowResults(self.flow_state)
@@ -213,10 +373,14 @@ impl<O: BitDenotation> DataflowResults<O> {
     pub fn sets(&self) -> &AllSets<O::Idx> {
         &self.0.sets
     }
+
+    pub fn operator(&self) -> &O {
+        &self.0.operator
+    }
 }
 
-// FIXME: This type shouldn't be public, but the graphviz::MirWithFlowState trait
-// references it in a method signature. Look into using `pub(crate)` to address this.
+/// State of a dataflow analysis; couples a collection of bit sets
+/// with operator used to initialize and merge bits during analysis.
 pub struct DataflowState<O: BitDenotation>
 {
     /// All the sets for the analysis. (Factored into its
@@ -228,6 +392,28 @@ pub struct DataflowState<O: BitDenotation>
     pub(crate) operator: O,
 }
 
+impl<O: BitDenotation> DataflowState<O> {
+    pub fn each_bit<F>(&self, words: &IdxSet<O::Idx>, f: F) where F: FnMut(O::Idx)
+    {
+        let bits_per_block = self.operator.bits_per_block();
+        words.each_bit(bits_per_block, f)
+    }
+
+    pub fn interpret_set<'c, P>(&self,
+                                o: &'c O,
+                                words: &IdxSet<O::Idx>,
+                                render_idx: &P)
+                                -> Vec<&'c Debug>
+        where P: Fn(&O, O::Idx) -> &Debug
+    {
+        let mut v = Vec::new();
+        self.each_bit(words, |i| {
+            v.push(render_idx(o, i));
+        });
+        v
+    }
+}
+
 #[derive(Debug)]
 pub struct AllSets<E: Idx> {
     /// Analysis bitwidth for each block.
@@ -251,9 +437,28 @@ pub struct AllSets<E: Idx> {
     on_entry_sets: Bits<E>,
 }
 
+/// Triple of sets associated with a given block.
+///
+/// Generally, one sets up `on_entry`, `gen_set`, and `kill_set` for
+/// each block individually, and then runs the dataflow analysis which
+/// iteratively modifies the various `on_entry` sets (but leaves the
+/// other two sets unchanged, since they represent the effect of the
+/// block, which should be invariant over the course of the analysis).
+///
+/// It is best to ensure that the intersection of `gen_set` and
+/// `kill_set` is empty; otherwise the results of the dataflow will
+/// have a hidden dependency on what order the bits are generated and
+/// killed during the iteration. (This is such a good idea that the
+/// `fn gen` and `fn kill` methods that set their state enforce this
+/// for you.)
 pub struct BlockSets<'a, E: Idx> {
+    /// Dataflow state immediately before control flow enters the given block.
     pub(crate) on_entry: &'a mut IdxSet<E>,
+
+    /// Bits that are set to 1 by the time we exit the given block.
     pub(crate) gen_set: &'a mut IdxSet<E>,
+
+    /// Bits that are set to 0 by the time we exit the given block.
     pub(crate) kill_set: &'a mut IdxSet<E>,
 }
 
@@ -302,7 +507,7 @@ pub trait DataflowOperator: BitwiseOperator {
     fn bottom_value() -> bool;
 }
 
-pub trait BitDenotation {
+pub trait BitDenotation: DataflowOperator {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
 
@@ -341,8 +546,7 @@ pub trait BitDenotation {
     /// the MIR.
     fn statement_effect(&self,
                         sets: &mut BlockSets<Self::Idx>,
-                        bb: mir::BasicBlock,
-                        idx_stmt: usize);
+                        location: Location);
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating
@@ -356,8 +560,7 @@ pub trait BitDenotation {
     /// terminator took.
     fn terminator_effect(&self,
                          sets: &mut BlockSets<Self::Idx>,
-                         bb: mir::BasicBlock,
-                         idx_term: usize);
+                         location: Location);
 
     /// Mutates the block-sets according to the (flow-dependent)
     /// effect of a successful return from a Call terminator.
@@ -385,8 +588,7 @@ pub trait BitDenotation {
                              dest_lval: &mir::Lvalue);
 }
 
-impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
-    where D: BitDenotation + DataflowOperator
+impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
 {
     pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
                mir: &'a Mir<'tcx>,
@@ -410,12 +612,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
         });
 
         DataflowAnalysis {
-            mir: mir,
-            dead_unwinds: dead_unwinds,
+            mir,
+            dead_unwinds,
             flow_state: DataflowState {
                 sets: AllSets {
-                    bits_per_block: bits_per_block,
-                    words_per_block: words_per_block,
+                    bits_per_block,
+                    words_per_block,
                     gen_sets: zeroes.clone(),
                     kill_sets: zeroes,
                     on_entry_sets: on_entry,
@@ -427,8 +629,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
     }
 }
 
-impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
-    where D: BitDenotation + DataflowOperator
+impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
 {
     /// Propagates the bits of `in_out` into all the successors of `bb`,
     /// using bitwise operator denoted by `self.operator`.
diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index 1255209322b..173396f2245 100644
--- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
@@ -58,9 +58,9 @@ impl<'tcx> Lift for LvalueElem<'tcx> {
                 ProjectionElem::Subslice { from: from, to: to },
             ProjectionElem::ConstantIndex {offset,min_length,from_end} =>
                 ProjectionElem::ConstantIndex {
-                    offset: offset,
-                    min_length: min_length,
-                    from_end: from_end
+                    offset,
+                    min_length,
+                    from_end,
                 },
             ProjectionElem::Downcast(a, u) =>
                 ProjectionElem::Downcast(a.clone(), u.clone()),
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
new file mode 100644
index 00000000000..c45c91011d9
--- /dev/null
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -0,0 +1,332 @@
+// 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::ty::{self, TyCtxt};
+use rustc::mir::*;
+use rustc::mir::tcx::RvalueInitializationState;
+use rustc::util::nodemap::FxHashMap;
+use rustc_data_structures::indexed_vec::{IndexVec};
+
+use syntax::codemap::DUMMY_SP;
+
+use std::collections::hash_map::Entry;
+use std::mem;
+
+use super::abs_domain::Lift;
+
+use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex};
+
+pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    data: MoveData<'tcx>,
+}
+
+pub enum MovePathError {
+    IllegalMove,
+    UnionMove { path: MovePathIndex },
+}
+
+impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+    fn new(mir: &'a Mir<'tcx>,
+           tcx: TyCtxt<'a, 'tcx, 'tcx>,
+           param_env: ty::ParamEnv<'tcx>)
+           -> Self {
+        let mut move_paths = IndexVec::new();
+        let mut path_map = IndexVec::new();
+
+        MoveDataBuilder {
+            mir,
+            tcx,
+            param_env,
+            data: MoveData {
+                moves: IndexVec::new(),
+                loc_map: LocationMap::new(mir),
+                rev_lookup: MovePathLookup {
+                    locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| {
+                        Self::new_move_path(&mut move_paths, &mut path_map, None, v)
+                    }).collect(),
+                    projections: FxHashMap(),
+                },
+                move_paths,
+                path_map,
+            }
+        }
+    }
+
+    fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
+                     path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>,
+                     parent: Option<MovePathIndex>,
+                     lvalue: Lvalue<'tcx>)
+                     -> MovePathIndex
+    {
+        let move_path = move_paths.push(MovePath {
+            next_sibling: None,
+            first_child: None,
+            parent,
+            lvalue,
+        });
+
+        if let Some(parent) = parent {
+            let next_sibling =
+                mem::replace(&mut move_paths[parent].first_child, Some(move_path));
+            move_paths[move_path].next_sibling = next_sibling;
+        }
+
+        let path_map_ent = path_map.push(vec![]);
+        assert_eq!(path_map_ent, move_path);
+        move_path
+    }
+
+    /// This creates a MovePath for a given lvalue, returning an `MovePathError`
+    /// if that lvalue can't be moved from.
+    ///
+    /// NOTE: lvalues behind references *do not* get a move path, which is
+    /// problematic for borrowck.
+    ///
+    /// Maybe we should have separate "borrowck" and "moveck" modes.
+    fn move_path_for(&mut self, lval: &Lvalue<'tcx>)
+                     -> Result<MovePathIndex, MovePathError>
+    {
+        debug!("lookup({:?})", lval);
+        match *lval {
+            Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]),
+            // error: can't move out of a static
+            Lvalue::Static(..) => Err(MovePathError::IllegalMove),
+            Lvalue::Projection(ref proj) => {
+                self.move_path_for_projection(lval, proj)
+            }
+        }
+    }
+
+    fn create_move_path(&mut self, lval: &Lvalue<'tcx>) {
+        // This is an assignment, not a move, so this not being a valid
+        // move path is OK.
+        let _ = self.move_path_for(lval);
+    }
+
+    fn move_path_for_projection(&mut self,
+                                lval: &Lvalue<'tcx>,
+                                proj: &LvalueProjection<'tcx>)
+                                -> Result<MovePathIndex, MovePathError>
+    {
+        let base = try!(self.move_path_for(&proj.base));
+        let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
+        match lv_ty.sty {
+            // error: can't move out of borrowed content
+            ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove),
+            // error: can't move out of struct with destructor
+            ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() =>
+                return Err(MovePathError::IllegalMove),
+            // move out of union - always move the entire union
+            ty::TyAdt(adt, _) if adt.is_union() =>
+                return Err(MovePathError::UnionMove { path: base }),
+            // error: can't move out of a slice
+            ty::TySlice(..) =>
+                return Err(MovePathError::IllegalMove),
+            ty::TyArray(..) => match proj.elem {
+                // error: can't move out of an array
+                ProjectionElem::Index(..) => return Err(MovePathError::IllegalMove),
+                _ => {
+                    // FIXME: still badly broken
+                }
+            },
+            _ => {}
+        };
+        match self.data.rev_lookup.projections.entry((base, proj.elem.lift())) {
+            Entry::Occupied(ent) => Ok(*ent.get()),
+            Entry::Vacant(ent) => {
+                let path = Self::new_move_path(
+                    &mut self.data.move_paths,
+                    &mut self.data.path_map,
+                    Some(base),
+                    lval.clone()
+                );
+                ent.insert(path);
+                Ok(path)
+            }
+        }
+    }
+
+    fn finalize(self) -> MoveData<'tcx> {
+        debug!("{}", {
+            debug!("moves for {:?}:", self.mir.span);
+            for (j, mo) in self.data.moves.iter_enumerated() {
+                debug!("    {:?} = {:?}", j, mo);
+            }
+            debug!("move paths for {:?}:", self.mir.span);
+            for (j, path) in self.data.move_paths.iter_enumerated() {
+                debug!("    {:?} = {:?}", j, path);
+            }
+            "done dumping moves"
+        });
+        self.data
+    }
+}
+
+pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
+                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     param_env: ty::ParamEnv<'tcx>)
+                                     -> MoveData<'tcx> {
+    let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
+
+    for (bb, block) in mir.basic_blocks().iter_enumerated() {
+        for (i, stmt) in block.statements.iter().enumerate() {
+            let source = Location { block: bb, statement_index: i };
+            builder.gather_statement(source, stmt);
+        }
+
+        let terminator_loc = Location {
+            block: bb,
+            statement_index: block.statements.len()
+        };
+        builder.gather_terminator(terminator_loc, block.terminator());
+    }
+
+    builder.finalize()
+}
+
+impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+    fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
+        debug!("gather_statement({:?}, {:?})", loc, stmt);
+        match stmt.kind {
+            StatementKind::Assign(ref lval, ref rval) => {
+                self.create_move_path(lval);
+                if let RvalueInitializationState::Shallow = rval.initialization_state() {
+                    // Box starts out uninitialized - need to create a separate
+                    // move-path for the interior so it will be separate from
+                    // the exterior.
+                    self.create_move_path(&lval.clone().deref());
+                }
+                self.gather_rvalue(loc, rval);
+            }
+            StatementKind::StorageLive(_) |
+            StatementKind::StorageDead(_) => {}
+            StatementKind::SetDiscriminant{ .. } => {
+                span_bug!(stmt.source_info.span,
+                          "SetDiscriminant should not exist during borrowck");
+            }
+            StatementKind::InlineAsm { .. } |
+            StatementKind::EndRegion(_) |
+            StatementKind::Validate(..) |
+            StatementKind::Nop => {}
+        }
+    }
+
+    fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) {
+        match *rvalue {
+            Rvalue::Use(ref operand) |
+            Rvalue::Repeat(ref operand, _) |
+            Rvalue::Cast(_, ref operand, _) |
+            Rvalue::UnaryOp(_, ref operand) => {
+                self.gather_operand(loc, operand)
+            }
+            Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) |
+            Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => {
+                self.gather_operand(loc, lhs);
+                self.gather_operand(loc, rhs);
+            }
+            Rvalue::Aggregate(ref _kind, ref operands) => {
+                for operand in operands {
+                    self.gather_operand(loc, operand);
+                }
+            }
+            Rvalue::Ref(..) |
+            Rvalue::Discriminant(..) |
+            Rvalue::Len(..) |
+            Rvalue::NullaryOp(NullOp::SizeOf, _) |
+            Rvalue::NullaryOp(NullOp::Box, _) => {
+                // This returns an rvalue with uninitialized contents. We can't
+                // move out of it here because it is an rvalue - assignments always
+                // completely initialize their lvalue.
+                //
+                // However, this does not matter - MIR building is careful to
+                // only emit a shallow free for the partially-initialized
+                // temporary.
+                //
+                // In any case, if we want to fix this, we have to register a
+                // special move and change the `statement_effect` functions.
+            }
+        }
+    }
+
+    fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
+        debug!("gather_terminator({:?}, {:?})", loc, term);
+        match term.kind {
+            TerminatorKind::Goto { target: _ } |
+            TerminatorKind::Resume |
+            TerminatorKind::Unreachable => { }
+
+            TerminatorKind::Return => {
+                self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
+            }
+
+            TerminatorKind::Assert { .. } |
+            TerminatorKind::SwitchInt { .. } => {
+                // branching terminators - these don't move anything
+            }
+
+            TerminatorKind::Drop { ref location, target: _, unwind: _ } => {
+                self.gather_move(loc, location);
+            }
+            TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
+                self.create_move_path(location);
+                self.gather_operand(loc, value);
+            }
+            TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
+                self.gather_operand(loc, func);
+                for arg in args {
+                    self.gather_operand(loc, arg);
+                }
+                if let Some((ref destination, _bb)) = *destination {
+                    self.create_move_path(destination);
+                }
+            }
+        }
+    }
+
+    fn gather_operand(&mut self, loc: Location, operand: &Operand<'tcx>) {
+        match *operand {
+            Operand::Constant(..) => {} // not-a-move
+            Operand::Consume(ref lval) => { // a move
+                self.gather_move(loc, lval);
+            }
+        }
+    }
+
+    fn gather_move(&mut self, loc: Location, lval: &Lvalue<'tcx>) {
+        debug!("gather_move({:?}, {:?})", loc, lval);
+
+        let lv_ty = lval.ty(self.mir, self.tcx).to_ty(self.tcx);
+        if !lv_ty.moves_by_default(self.tcx, self.param_env, DUMMY_SP) {
+            debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", loc, lval, lv_ty);
+            return
+        }
+
+        let path = match self.move_path_for(lval) {
+            Ok(path) | Err(MovePathError::UnionMove { path }) => path,
+            Err(MovePathError::IllegalMove) => {
+                // Moving out of a bad path. Eventually, this should be a MIR
+                // borrowck error instead of a bug.
+                span_bug!(self.mir.span,
+                          "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}",
+                          lval, lv_ty, loc);
+            }
+        };
+        let move_out = self.data.moves.push(MoveOut { path: path, source: loc });
+
+        debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}",
+               loc, lval, move_out, path);
+
+        self.data.path_map[path].push(move_out);
+        self.data.loc_map[loc].push(move_out);
+    }
+}
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index 20a61418d85..d2d80649846 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -11,15 +11,10 @@
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
-use rustc::mir::tcx::RvalueInitializationState;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::{IndexVec};
 
-use syntax::codemap::DUMMY_SP;
-
-use std::collections::hash_map::Entry;
 use std::fmt;
-use std::mem;
 use std::ops::{Index, IndexMut};
 
 use self::abs_domain::{AbstractElem, Lift};
@@ -63,6 +58,9 @@ pub(crate) mod indexes {
 
     /// Index into MoveData.moves.
     new_index!(MoveOutIndex, "mo");
+
+    /// Index into Borrows.locations
+    new_index!(BorrowIndex, "bw");
 }
 
 pub use self::indexes::MovePathIndex;
@@ -110,6 +108,12 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> {
     }
 }
 
+impl<'tcx> fmt::Display for MovePath<'tcx> {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        write!(w, "{:?}", self.lvalue)
+    }
+}
+
 #[derive(Debug)]
 pub struct MoveData<'tcx> {
     pub move_paths: IndexVec<MovePathIndex, MovePath<'tcx>>,
@@ -191,154 +195,7 @@ pub struct MovePathLookup<'tcx> {
     projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
 }
 
-pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> {
-    mir: &'a Mir<'tcx>,
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    data: MoveData<'tcx>,
-}
-
-pub enum MovePathError {
-    IllegalMove,
-    UnionMove { path: MovePathIndex },
-}
-
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
-    fn new(mir: &'a Mir<'tcx>,
-           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-           param_env: ty::ParamEnv<'tcx>)
-           -> Self {
-        let mut move_paths = IndexVec::new();
-        let mut path_map = IndexVec::new();
-
-        MoveDataBuilder {
-            mir: mir,
-            tcx: tcx,
-            param_env: param_env,
-            data: MoveData {
-                moves: IndexVec::new(),
-                loc_map: LocationMap::new(mir),
-                rev_lookup: MovePathLookup {
-                    locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| {
-                        Self::new_move_path(&mut move_paths, &mut path_map, None, v)
-                    }).collect(),
-                    projections: FxHashMap(),
-                },
-                move_paths: move_paths,
-                path_map: path_map,
-            }
-        }
-    }
-
-    fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
-                     path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>,
-                     parent: Option<MovePathIndex>,
-                     lvalue: Lvalue<'tcx>)
-                     -> MovePathIndex
-    {
-        let move_path = move_paths.push(MovePath {
-            next_sibling: None,
-            first_child: None,
-            parent: parent,
-            lvalue: lvalue
-        });
-
-        if let Some(parent) = parent {
-            let next_sibling =
-                mem::replace(&mut move_paths[parent].first_child, Some(move_path));
-            move_paths[move_path].next_sibling = next_sibling;
-        }
-
-        let path_map_ent = path_map.push(vec![]);
-        assert_eq!(path_map_ent, move_path);
-        move_path
-    }
-
-    /// This creates a MovePath for a given lvalue, returning an `MovePathError`
-    /// if that lvalue can't be moved from.
-    ///
-    /// NOTE: lvalues behind references *do not* get a move path, which is
-    /// problematic for borrowck.
-    ///
-    /// Maybe we should have separate "borrowck" and "moveck" modes.
-    fn move_path_for(&mut self, lval: &Lvalue<'tcx>)
-                     -> Result<MovePathIndex, MovePathError>
-    {
-        debug!("lookup({:?})", lval);
-        match *lval {
-            Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]),
-            // error: can't move out of a static
-            Lvalue::Static(..) => Err(MovePathError::IllegalMove),
-            Lvalue::Projection(ref proj) => {
-                self.move_path_for_projection(lval, proj)
-            }
-        }
-    }
-
-    fn create_move_path(&mut self, lval: &Lvalue<'tcx>) {
-        // This is an assignment, not a move, so this not being a valid
-        // move path is OK.
-        let _ = self.move_path_for(lval);
-    }
-
-    fn move_path_for_projection(&mut self,
-                                lval: &Lvalue<'tcx>,
-                                proj: &LvalueProjection<'tcx>)
-                                -> Result<MovePathIndex, MovePathError>
-    {
-        let base = try!(self.move_path_for(&proj.base));
-        let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
-        match lv_ty.sty {
-            // error: can't move out of borrowed content
-            ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove),
-            // error: can't move out of struct with destructor
-            ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() =>
-                return Err(MovePathError::IllegalMove),
-            // move out of union - always move the entire union
-            ty::TyAdt(adt, _) if adt.is_union() =>
-                return Err(MovePathError::UnionMove { path: base }),
-            // error: can't move out of a slice
-            ty::TySlice(..) =>
-                return Err(MovePathError::IllegalMove),
-            ty::TyArray(..) => match proj.elem {
-                // error: can't move out of an array
-                ProjectionElem::Index(..) => return Err(MovePathError::IllegalMove),
-                _ => {
-                    // FIXME: still badly broken
-                }
-            },
-            _ => {}
-        };
-        match self.data.rev_lookup.projections.entry((base, proj.elem.lift())) {
-            Entry::Occupied(ent) => Ok(*ent.get()),
-            Entry::Vacant(ent) => {
-                let path = Self::new_move_path(
-                    &mut self.data.move_paths,
-                    &mut self.data.path_map,
-                    Some(base),
-                    lval.clone()
-                );
-                ent.insert(path);
-                Ok(path)
-            }
-        }
-    }
-
-    fn finalize(self) -> MoveData<'tcx> {
-        debug!("{}", {
-            debug!("moves for {:?}:", self.mir.span);
-            for (j, mo) in self.data.moves.iter_enumerated() {
-                debug!("    {:?} = {:?}", j, mo);
-            }
-            debug!("move paths for {:?}:", self.mir.span);
-            for (j, path) in self.data.move_paths.iter_enumerated() {
-                debug!("    {:?} = {:?}", j, path);
-            }
-            "done dumping moves"
-        });
-        self.data
-    }
-}
+mod builder;
 
 #[derive(Copy, Clone, Debug)]
 pub enum LookupResult {
@@ -375,165 +232,6 @@ impl<'a, 'tcx> MoveData<'tcx> {
                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         param_env: ty::ParamEnv<'tcx>)
                         -> Self {
-        gather_moves(mir, tcx, param_env)
-    }
-}
-
-fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
-                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          param_env: ty::ParamEnv<'tcx>)
-                          -> MoveData<'tcx> {
-    let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
-
-    for (bb, block) in mir.basic_blocks().iter_enumerated() {
-        for (i, stmt) in block.statements.iter().enumerate() {
-            let source = Location { block: bb, statement_index: i };
-            builder.gather_statement(source, stmt);
-        }
-
-        let terminator_loc = Location {
-            block: bb,
-            statement_index: block.statements.len()
-        };
-        builder.gather_terminator(terminator_loc, block.terminator());
-    }
-
-    builder.finalize()
-}
-
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
-    fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
-        debug!("gather_statement({:?}, {:?})", loc, stmt);
-        match stmt.kind {
-            StatementKind::Assign(ref lval, ref rval) => {
-                self.create_move_path(lval);
-                if let RvalueInitializationState::Shallow = rval.initialization_state() {
-                    // Box starts out uninitialized - need to create a separate
-                    // move-path for the interior so it will be separate from
-                    // the exterior.
-                    self.create_move_path(&lval.clone().deref());
-                }
-                self.gather_rvalue(loc, rval);
-            }
-            StatementKind::StorageLive(_) |
-            StatementKind::StorageDead(_) => {}
-            StatementKind::SetDiscriminant{ .. } => {
-                span_bug!(stmt.source_info.span,
-                          "SetDiscriminant should not exist during borrowck");
-            }
-            StatementKind::InlineAsm { .. } |
-            StatementKind::EndRegion(_) |
-            StatementKind::Validate(..) |
-            StatementKind::Nop => {}
-        }
-    }
-
-    fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) {
-        match *rvalue {
-            Rvalue::Use(ref operand) |
-            Rvalue::Repeat(ref operand, _) |
-            Rvalue::Cast(_, ref operand, _) |
-            Rvalue::UnaryOp(_, ref operand) => {
-                self.gather_operand(loc, operand)
-            }
-            Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) |
-            Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => {
-                self.gather_operand(loc, lhs);
-                self.gather_operand(loc, rhs);
-            }
-            Rvalue::Aggregate(ref _kind, ref operands) => {
-                for operand in operands {
-                    self.gather_operand(loc, operand);
-                }
-            }
-            Rvalue::Ref(..) |
-            Rvalue::Discriminant(..) |
-            Rvalue::Len(..) |
-            Rvalue::NullaryOp(NullOp::SizeOf, _) |
-            Rvalue::NullaryOp(NullOp::Box, _) => {
-                // This returns an rvalue with uninitialized contents. We can't
-                // move out of it here because it is an rvalue - assignments always
-                // completely initialize their lvalue.
-                //
-                // However, this does not matter - MIR building is careful to
-                // only emit a shallow free for the partially-initialized
-                // temporary.
-                //
-                // In any case, if we want to fix this, we have to register a
-                // special move and change the `statement_effect` functions.
-            }
-        }
-    }
-
-    fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
-        debug!("gather_terminator({:?}, {:?})", loc, term);
-        match term.kind {
-            TerminatorKind::Goto { target: _ } |
-            TerminatorKind::Resume |
-            TerminatorKind::Unreachable => { }
-
-            TerminatorKind::Return => {
-                self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
-            }
-
-            TerminatorKind::Assert { .. } |
-            TerminatorKind::SwitchInt { .. } => {
-                // branching terminators - these don't move anything
-            }
-
-            TerminatorKind::Drop { ref location, target: _, unwind: _ } => {
-                self.gather_move(loc, location);
-            }
-            TerminatorKind::DropAndReplace { ref location, ref value, .. } => {
-                self.create_move_path(location);
-                self.gather_operand(loc, value);
-            }
-            TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
-                self.gather_operand(loc, func);
-                for arg in args {
-                    self.gather_operand(loc, arg);
-                }
-                if let Some((ref destination, _bb)) = *destination {
-                    self.create_move_path(destination);
-                }
-            }
-        }
-    }
-
-    fn gather_operand(&mut self, loc: Location, operand: &Operand<'tcx>) {
-        match *operand {
-            Operand::Constant(..) => {} // not-a-move
-            Operand::Consume(ref lval) => { // a move
-                self.gather_move(loc, lval);
-            }
-        }
-    }
-
-    fn gather_move(&mut self, loc: Location, lval: &Lvalue<'tcx>) {
-        debug!("gather_move({:?}, {:?})", loc, lval);
-
-        let lv_ty = lval.ty(self.mir, self.tcx).to_ty(self.tcx);
-        if !lv_ty.moves_by_default(self.tcx, self.param_env, DUMMY_SP) {
-            debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", loc, lval, lv_ty);
-            return
-        }
-
-        let path = match self.move_path_for(lval) {
-            Ok(path) | Err(MovePathError::UnionMove { path }) => path,
-            Err(MovePathError::IllegalMove) => {
-                // Moving out of a bad path. Eventually, this should be a MIR
-                // borrowck error instead of a bug.
-                span_bug!(self.mir.span,
-                          "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}",
-                          lval, lv_ty, loc);
-            }
-        };
-        let move_out = self.data.moves.push(MoveOut { path: path, source: loc });
-
-        debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}",
-               loc, lval, move_out, path);
-
-        self.data.path_map[path].push(move_out);
-        self.data.loc_map[loc].push(move_out);
+        builder::gather_moves(mir, tcx, param_env)
     }
 }
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 34170a6609c..83a8ce34c69 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -195,6 +195,50 @@ instead of using a `const fn`, or refactoring the code to a functional style to
 avoid mutation if possible.
 "##,
 
+E0381: r##"
+It is not allowed to use or capture an uninitialized variable. For example:
+
+```compile_fail,E0381
+fn main() {
+    let x: i32;
+    let y = x; // error, use of possibly uninitialized variable
+}
+```
+
+To fix this, ensure that any declared variables are initialized before being
+used. Example:
+
+```
+fn main() {
+    let x: i32 = 0;
+    let y = x; // ok!
+}
+```
+"##,
+
+E0384: r##"
+This error occurs when an attempt is made to reassign an immutable variable.
+For example:
+
+```compile_fail,E0384
+fn main() {
+    let x = 3;
+    x = 5; // error, reassignment of immutable variable
+}
+```
+
+By default, variables in Rust are immutable. To fix this error, add the keyword
+`mut` after the keyword `let` when declaring the variable. For example:
+
+```
+fn main() {
+    let mut x = 3;
+    x = 5;
+}
+```
+"##,
+
+
 E0394: r##"
 A static was referred to by value by another static.
 
@@ -438,9 +482,516 @@ static A : &'static u32 = &S.a; // ok!
 ```
 "##,
 
+E0499: r##"
+A variable was borrowed as mutable more than once. Erroneous code example:
+
+```compile_fail,E0499
+let mut i = 0;
+let mut x = &mut i;
+let mut a = &mut i;
+// error: cannot borrow `i` as mutable more than once at a time
+```
+
+Please note that in rust, you can either have many immutable references, or one
+mutable reference. Take a look at
+https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
+information. Example:
+
+
+```
+let mut i = 0;
+let mut x = &mut i; // ok!
+
+// or:
+let mut i = 0;
+let a = &i; // ok!
+let b = &i; // still ok!
+let c = &i; // still ok!
+```
+"##,
+
+E0500: r##"
+A borrowed variable was used in another closure. Example of erroneous code:
+
+```compile_fail
+fn you_know_nothing(jon_snow: &mut i32) {
+    let nights_watch = || {
+        *jon_snow = 2;
+    };
+    let starks = || {
+        *jon_snow = 3; // error: closure requires unique access to `jon_snow`
+                       //        but it is already borrowed
+    };
+}
+```
+
+In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it
+cannot be borrowed by the `starks` closure at the same time. To fix this issue,
+you can put the closure in its own scope:
+
+```
+fn you_know_nothing(jon_snow: &mut i32) {
+    {
+        let nights_watch = || {
+            *jon_snow = 2;
+        };
+    } // At this point, `jon_snow` is free.
+    let starks = || {
+        *jon_snow = 3;
+    };
+}
+```
+
+Or, if the type implements the `Clone` trait, you can clone it between
+closures:
+
+```
+fn you_know_nothing(jon_snow: &mut i32) {
+    let mut jon_copy = jon_snow.clone();
+    let nights_watch = || {
+        jon_copy = 2;
+    };
+    let starks = || {
+        *jon_snow = 3;
+    };
+}
+```
+"##,
+
+E0501: r##"
+This error indicates that a mutable variable is being used while it is still
+captured by a closure. Because the closure has borrowed the variable, it is not
+available for use until the closure goes out of scope.
+
+Note that a capture will either move or borrow a variable, but in this
+situation, the closure is borrowing the variable. Take a look at
+http://rustbyexample.com/fn/closures/capture.html for more information about
+capturing.
+
+Example of erroneous code:
+
+```compile_fail,E0501
+fn inside_closure(x: &mut i32) {
+    // Actions which require unique access
+}
+
+fn outside_closure(x: &mut i32) {
+    // Actions which require unique access
+}
+
+fn foo(a: &mut i32) {
+    let bar = || {
+        inside_closure(a)
+    };
+    outside_closure(a); // error: cannot borrow `*a` as mutable because previous
+                        //        closure requires unique access.
+}
+```
+
+To fix this error, you can place the closure in its own scope:
+
+```
+fn inside_closure(x: &mut i32) {}
+fn outside_closure(x: &mut i32) {}
+
+fn foo(a: &mut i32) {
+    {
+        let bar = || {
+            inside_closure(a)
+        };
+    } // borrow on `a` ends.
+    outside_closure(a); // ok!
+}
+```
+
+Or you can pass the variable as a parameter to the closure:
+
+```
+fn inside_closure(x: &mut i32) {}
+fn outside_closure(x: &mut i32) {}
+
+fn foo(a: &mut i32) {
+    let bar = |s: &mut i32| {
+        inside_closure(s)
+    };
+    outside_closure(a);
+    bar(a);
+}
+```
+
+It may be possible to define the closure later:
+
+```
+fn inside_closure(x: &mut i32) {}
+fn outside_closure(x: &mut i32) {}
+
+fn foo(a: &mut i32) {
+    outside_closure(a);
+    let bar = || {
+        inside_closure(a)
+    };
+}
+```
+"##,
+
+E0502: r##"
+This error indicates that you are trying to borrow a variable as mutable when it
+has already been borrowed as immutable.
+
+Example of erroneous code:
+
+```compile_fail,E0502
+fn bar(x: &mut i32) {}
+fn foo(a: &mut i32) {
+    let ref y = a; // a is borrowed as immutable.
+    bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed
+            //        as immutable
+}
+```
+
+To fix this error, ensure that you don't have any other references to the
+variable before trying to access it mutably:
+
+```
+fn bar(x: &mut i32) {}
+fn foo(a: &mut i32) {
+    bar(a);
+    let ref y = a; // ok!
+}
+```
+
+For more information on the rust ownership system, take a look at
+https://doc.rust-lang.org/stable/book/references-and-borrowing.html.
+"##,
+
+E0503: r##"
+A value was used after it was mutably borrowed.
+
+Example of erroneous code:
+
+```compile_fail,E0503
+fn main() {
+    let mut value = 3;
+    // Create a mutable borrow of `value`. This borrow
+    // lives until the end of this function.
+    let _borrow = &mut value;
+    let _sum = value + 1; // error: cannot use `value` because
+                          //        it was mutably borrowed
+}
+```
+
+In this example, `value` is mutably borrowed by `borrow` and cannot be
+used to calculate `sum`. This is not possible because this would violate
+Rust's mutability rules.
+
+You can fix this error by limiting the scope of the borrow:
+
+```
+fn main() {
+    let mut value = 3;
+    // By creating a new block, you can limit the scope
+    // of the reference.
+    {
+        let _borrow = &mut value; // Use `_borrow` inside this block.
+    }
+    // The block has ended and with it the borrow.
+    // You can now use `value` again.
+    let _sum = value + 1;
+}
+```
+
+Or by cloning `value` before borrowing it:
+
+```
+fn main() {
+    let mut value = 3;
+    // We clone `value`, creating a copy.
+    let value_cloned = value.clone();
+    // The mutable borrow is a reference to `value` and
+    // not to `value_cloned`...
+    let _borrow = &mut value;
+    // ... which means we can still use `value_cloned`,
+    let _sum = value_cloned + 1;
+    // even though the borrow only ends here.
+}
+```
+
+You can find more information about borrowing in the rust-book:
+http://doc.rust-lang.org/stable/book/references-and-borrowing.html
+"##,
+
+E0504: r##"
+This error occurs when an attempt is made to move a borrowed variable into a
+closure.
+
+Example of erroneous code:
+
+```compile_fail,E0504
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let fancy_num = FancyNum { num: 5 };
+    let fancy_ref = &fancy_num;
+
+    let x = move || {
+        println!("child function: {}", fancy_num.num);
+        // error: cannot move `fancy_num` into closure because it is borrowed
+    };
+
+    x();
+    println!("main function: {}", fancy_ref.num);
+}
+```
+
+Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
+the closure `x`. There is no way to move a value into a closure while it is
+borrowed, as that would invalidate the borrow.
+
+If the closure can't outlive the value being moved, try using a reference
+rather than moving:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let fancy_num = FancyNum { num: 5 };
+    let fancy_ref = &fancy_num;
+
+    let x = move || {
+        // fancy_ref is usable here because it doesn't move `fancy_num`
+        println!("child function: {}", fancy_ref.num);
+    };
+
+    x();
+
+    println!("main function: {}", fancy_num.num);
+}
+```
+
+If the value has to be borrowed and then moved, try limiting the lifetime of
+the borrow using a scoped block:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let fancy_num = FancyNum { num: 5 };
+
+    {
+        let fancy_ref = &fancy_num;
+        println!("main function: {}", fancy_ref.num);
+        // `fancy_ref` goes out of scope here
+    }
+
+    let x = move || {
+        // `fancy_num` can be moved now (no more references exist)
+        println!("child function: {}", fancy_num.num);
+    };
+
+    x();
+}
+```
+
+If the lifetime of a reference isn't enough, such as in the case of threading,
+consider using an `Arc` to create a reference-counted value:
+
+```
+use std::sync::Arc;
+use std::thread;
+
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let fancy_ref1 = Arc::new(FancyNum { num: 5 });
+    let fancy_ref2 = fancy_ref1.clone();
+
+    let x = thread::spawn(move || {
+        // `fancy_ref1` can be moved and has a `'static` lifetime
+        println!("child thread: {}", fancy_ref1.num);
+    });
+
+    x.join().expect("child thread should finish");
+    println!("main thread: {}", fancy_ref2.num);
+}
+```
+"##,
+
+E0505: r##"
+A value was moved out while it was still borrowed.
+
+Erroneous code example:
+
+```compile_fail,E0505
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(x);
+    }
+}
+```
+
+Here, the function `eat` takes the ownership of `x`. However,
+`x` cannot be moved because it was borrowed to `_ref_to_val`.
+To fix that you can do few different things:
+
+* Try to avoid moving the variable.
+* Release borrow before move.
+* Implement the `Copy` trait on the type.
+
+Examples:
+
+```
+struct Value {}
+
+fn eat(val: &Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(&x); // pass by reference, if it's possible
+    }
+}
+```
+
+Or:
+
+```
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+    }
+    eat(x); // release borrow and then move it.
+}
+```
+
+Or:
+
+```
+#[derive(Clone, Copy)] // implement Copy trait
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(x); // it will be copied here.
+    }
+}
+```
+
+You can find more information about borrowing in the rust-book:
+http://doc.rust-lang.org/stable/book/references-and-borrowing.html
+"##,
+
+E0506: r##"
+This error occurs when an attempt is made to assign to a borrowed value.
+
+Example of erroneous code:
+
+```compile_fail,E0506
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy_num = FancyNum { num: 5 };
+    let fancy_ref = &fancy_num;
+    fancy_num = FancyNum { num: 6 };
+    // error: cannot assign to `fancy_num` because it is borrowed
+
+    println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
+}
+```
+
+Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
+be assigned to a new value as it would invalidate the reference.
+
+Alternatively, we can move out of `fancy_num` into a second `fancy_num`:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy_num = FancyNum { num: 5 };
+    let moved_num = fancy_num;
+    fancy_num = FancyNum { num: 6 };
+
+    println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num);
+}
+```
+
+If the value has to be borrowed, try limiting the lifetime of the borrow using
+a scoped block:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy_num = FancyNum { num: 5 };
+
+    {
+        let fancy_ref = &fancy_num;
+        println!("Ref: {}", fancy_ref.num);
+    }
+
+    // Works because `fancy_ref` is no longer in scope
+    fancy_num = FancyNum { num: 6 };
+    println!("Num: {}", fancy_num.num);
+}
+```
+
+Or by moving the reference into a function:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy_num = FancyNum { num: 5 };
+
+    print_fancy_ref(&fancy_num);
+
+    // Works because function borrow has ended
+    fancy_num = FancyNum { num: 6 };
+    println!("Num: {}", fancy_num.num);
+}
+
+fn print_fancy_ref(fancy_ref: &FancyNum){
+    println!("Ref: {}", fancy_ref.num);
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
+    E0524, // two closures require unique access to `..` at the same time
     E0526, // shuffle indices are not constant
     E0625, // thread-local statics cannot be accessed at compile-time
 }
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index fa54925c6e7..61d128fc847 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -22,16 +22,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
         // We have to eagerly translate the "spine" of the statements
         // in order to get the lexical scoping correctly.
         let stmts = mirror_stmts(cx, self.id, &*self.stmts);
-        let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id);
-        let opt_destruction_extent = opt_def_id.and_then(|def_id| {
-            cx.tcx.region_maps(def_id).opt_destruction_extent(self.id)
-        });
+        let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.id);
         Block {
             targeted_by_break: self.targeted_by_break,
             extent: CodeExtent::Misc(self.id),
-            opt_destruction_extent: opt_destruction_extent,
+            opt_destruction_extent,
             span: self.span,
-            stmts: stmts,
+            stmts,
             expr: self.expr.to_ref(),
         }
     }
@@ -42,11 +39,8 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 stmts: &'tcx [hir::Stmt])
                                 -> Vec<StmtRef<'tcx>> {
     let mut result = vec![];
-    let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id);
     for (index, stmt) in stmts.iter().enumerate() {
-        let opt_dxn_ext = opt_def_id.and_then(|def_id| {
-            cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id())
-        });
+        let opt_dxn_ext = cx.region_maps.opt_destruction_extent(stmt.node.id());
         match stmt.node {
             hir::StmtExpr(ref expr, id) |
             hir::StmtSemi(ref expr, id) => {
@@ -79,7 +73,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                             kind: StmtKind::Let {
                                 remainder_scope: remainder_extent,
                                 init_scope: CodeExtent::Misc(id),
-                                pattern: pattern,
+                                pattern,
                                 initializer: local.init.to_ref(),
                             },
                             opt_destruction_extent: opt_dxn_ext,
@@ -99,7 +93,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let temp_lifetime = cx.region_maps.temporary_scope(block.id);
     let expr = Expr {
         ty: block_ty,
-        temp_lifetime: temp_lifetime,
+        temp_lifetime,
         span: block.span,
         kind: ExprKind::Block { body: block },
     };
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 617c3c77bbb..944fb8e8332 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -42,7 +42,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
 
         // Next, wrap this up in the expr's scope.
         expr = Expr {
-            temp_lifetime: temp_lifetime,
+            temp_lifetime,
             ty: expr.ty,
             span: self.span,
             kind: ExprKind::Scope {
@@ -54,11 +54,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
         // Finally, create a destruction scope, if any.
         if let Some(extent) = cx.region_maps.opt_destruction_extent(self.id) {
             expr = Expr {
-                temp_lifetime: temp_lifetime,
+                temp_lifetime,
                 ty: expr.ty,
                 span: self.span,
                 kind: ExprKind::Scope {
-                    extent: extent,
+                    extent,
                     value: expr.to_ref(),
                 },
             };
@@ -136,7 +136,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                   }),
                 span,
                 kind: ExprKind::Borrow {
-                    region: region,
+                    region,
                     borrow_kind: to_borrow_kind(m),
                     arg: expr.to_ref(),
                 },
@@ -173,7 +173,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             ExprKind::Call {
                 ty: expr.ty,
                 fun: expr.to_ref(),
-                args: args,
+                args,
             }
         }
 
@@ -191,7 +191,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
                 let tupled_args = Expr {
                     ty: cx.tcx.mk_tup(arg_tys, false),
-                    temp_lifetime: temp_lifetime,
+                    temp_lifetime,
                     span: expr.span,
                     kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() },
                 };
@@ -228,8 +228,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         })
                         .collect();
                     ExprKind::Adt {
-                        adt_def: adt_def,
-                        substs: substs,
+                        adt_def,
+                        substs,
                         variant_index: index,
                         fields: field_refs,
                         base: None,
@@ -250,7 +250,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 _ => span_bug!(expr.span, "type of & not region"),
             };
             ExprKind::Borrow {
-                region: region,
+                region,
                 borrow_kind: to_borrow_kind(mutbl),
                 arg: expr.to_ref(),
             }
@@ -320,7 +320,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     _ => {
                         let op = bin_op(op.node);
                         ExprKind::Binary {
-                            op: op,
+                            op,
                             lhs: lhs.to_ref(),
                             rhs: rhs.to_ref(),
                         }
@@ -384,7 +384,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                             ExprKind::Adt {
                                 adt_def: adt,
                                 variant_index: 0,
-                                substs: substs,
+                                substs,
                                 fields: field_refs,
                                 base: base.as_ref().map(|base| {
                                     FruInfo {
@@ -410,7 +410,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                     ExprKind::Adt {
                                         adt_def: adt,
                                         variant_index: index,
-                                        substs: substs,
+                                        substs,
                                         fields: field_refs,
                                         base: None,
                                     }
@@ -446,8 +446,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             });
             ExprKind::Closure {
                 closure_id: def_id,
-                substs: substs,
-                upvars: upvars,
+                substs,
+                upvars,
             }
         }
 
@@ -458,7 +458,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => {
             ExprKind::InlineAsm {
-                asm: asm,
+                asm,
                 outputs: outputs.to_ref(),
                 inputs: inputs.to_ref(),
             }
@@ -477,7 +477,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
             ExprKind::Repeat {
                 value: v.to_ref(),
-                count: count,
+                count,
             }
         }
         hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() },
@@ -570,10 +570,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     };
 
     Expr {
-        temp_lifetime: temp_lifetime,
+        temp_lifetime,
         ty: expr_ty,
         span: expr.span,
-        kind: kind,
+        kind,
     }
 }
 
@@ -587,7 +587,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
          cx.tables().node_substs(expr.hir_id))
     });
     Expr {
-        temp_lifetime: temp_lifetime,
+        temp_lifetime,
         ty: cx.tcx().mk_fn_def(def_id, substs),
         span: expr.span,
         kind: ExprKind::Literal {
@@ -637,8 +637,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::Const(def_id) |
         Def::AssociatedConst(def_id) => ExprKind::Literal {
             literal: Literal::Item {
-                def_id: def_id,
-                substs: substs,
+                def_id,
+                substs,
             },
         },
 
@@ -649,9 +649,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 // We return a completely different ExprKind here to account for this special case.
                 ty::TyAdt(adt_def, substs) => {
                     ExprKind::Adt {
-                        adt_def: adt_def,
+                        adt_def,
                         variant_index: adt_def.variant_index_with_id(def_id),
-                        substs: substs,
+                        substs,
                         fields: vec![],
                         base: None,
                     }
@@ -712,12 +712,12 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                                        });
                     Expr {
                         ty: closure_ty,
-                        temp_lifetime: temp_lifetime,
+                        temp_lifetime,
                         span: expr.span,
                         kind: ExprKind::Deref {
                             arg: Expr {
                                 ty: ref_closure_ty,
-                                temp_lifetime: temp_lifetime,
+                                temp_lifetime,
                                 span: expr.span,
                                 kind: ExprKind::SelfRef,
                             }
@@ -733,12 +733,12 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                                        });
                     Expr {
                         ty: closure_ty,
-                        temp_lifetime: temp_lifetime,
+                        temp_lifetime,
                         span: expr.span,
                         kind: ExprKind::Deref {
                             arg: Expr {
                                 ty: ref_closure_ty,
-                                temp_lifetime: temp_lifetime,
+                                temp_lifetime,
                                 span: expr.span,
                                 kind: ExprKind::SelfRef,
                             }.to_ref(),
@@ -748,7 +748,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty::ClosureKind::FnOnce => {
                     Expr {
                         ty: closure_ty,
-                        temp_lifetime: temp_lifetime,
+                        temp_lifetime,
                         span: expr.span,
                         kind: ExprKind::SelfRef,
                     }
@@ -772,7 +772,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty::UpvarCapture::ByRef(borrow) => {
                     ExprKind::Deref {
                         arg: Expr {
-                            temp_lifetime: temp_lifetime,
+                            temp_lifetime,
                             ty: cx.tcx.mk_ref(borrow.region,
                                               ty::TypeAndMut {
                                                   ty: var_ty,
@@ -857,7 +857,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let temp_lifetime = cx.region_maps.temporary_scope(expr.id);
     let fun = method_callee(cx, expr, custom_callee);
     let ref_expr = Expr {
-        temp_lifetime: temp_lifetime,
+        temp_lifetime,
         ty: ref_ty,
         span: expr.span,
         kind: ExprKind::Call {
@@ -887,7 +887,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     let var_ty = cx.tables()
                    .node_id_to_type(cx.tcx.hir.node_to_hir_id(var_node_id));
     let captured_var = Expr {
-        temp_lifetime: temp_lifetime,
+        temp_lifetime,
         ty: var_ty,
         span: closure_expr.span,
         kind: convert_var(cx, closure_expr, freevar.def),
@@ -901,12 +901,12 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty::BorrowKind::MutBorrow => BorrowKind::Mut,
             };
             Expr {
-                temp_lifetime: temp_lifetime,
+                temp_lifetime,
                 ty: freevar_ty,
                 span: closure_expr.span,
                 kind: ExprKind::Borrow {
                     region: upvar_borrow.region,
-                    borrow_kind: borrow_kind,
+                    borrow_kind,
                     arg: captured_var.to_ref(),
                 },
             }.to_ref()
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index ea8624930e5..dba625e98fd 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -14,9 +14,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 */
 
-#![crate_name = "rustc_mir"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![deny(warnings)]
 
 #![feature(box_patterns)]
@@ -32,6 +29,7 @@ extern crate graphviz as dot;
 #[macro_use]
 extern crate rustc;
 extern crate rustc_data_structures;
+extern crate rustc_errors;
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
@@ -42,10 +40,11 @@ extern crate rustc_const_math;
 extern crate rustc_const_eval;
 extern crate core; // for NonZero
 
-pub mod diagnostics;
+mod diagnostics;
 
+mod borrow_check;
 mod build;
-pub mod dataflow;
+mod dataflow;
 mod hair;
 mod shim;
 pub mod transform;
@@ -54,6 +53,7 @@ pub mod util;
 use rustc::ty::maps::Providers;
 
 pub fn provide(providers: &mut Providers) {
+    borrow_check::provide(providers);
     shim::provide(providers);
     transform::provide(providers);
 }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 62e762be93a..6bee1ceff89 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -17,6 +17,7 @@ use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
+use rustc_const_math::{ConstInt, ConstUsize};
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
@@ -98,14 +99,25 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         ty::InstanceDef::DropGlue(def_id, ty) => {
             build_drop_shim(tcx, def_id, ty)
         }
+        ty::InstanceDef::CloneShim(def_id, ty) => {
+            let name = tcx.item_name(def_id).as_str();
+            if name == "clone" {
+                build_clone_shim(tcx, def_id, ty)
+            } else if name == "clone_from" {
+                debug!("make_shim({:?}: using default trait implementation", instance);
+                return tcx.optimized_mir(def_id);
+            } else {
+                bug!("builtin clone shim {:?} not supported", instance)
+            }
+        }
         ty::InstanceDef::Intrinsic(_) => {
             bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
         }
     };
-        debug!("make_shim({:?}) = untransformed {:?}", instance, result);
-        no_landing_pads::no_landing_pads(tcx, &mut result);
-        simplify::simplify_cfg(&mut result);
-        add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
+    debug!("make_shim({:?}) = untransformed {:?}", instance, result);
+    no_landing_pads::no_landing_pads(tcx, &mut result);
+    simplify::simplify_cfg(&mut result);
+    add_call_guards::CriticalCallEdges.add_call_guards(&mut result);
     debug!("make_shim({:?}) = {:?}", instance, result);
 
     tcx.alloc_mir(result)
@@ -259,6 +271,374 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
     }
 }
 
+/// Build a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
+fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+                              def_id: DefId,
+                              self_ty: ty::Ty<'tcx>)
+                              -> Mir<'tcx>
+{
+    debug!("build_clone_shim(def_id={:?})", def_id);
+
+    let mut builder = CloneShimBuilder::new(tcx, def_id);
+    let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span);
+
+    match self_ty.sty {
+        _ if is_copy => builder.copy_shim(),
+        ty::TyArray(ty, len) => builder.array_shim(ty, len),
+        ty::TyTuple(tys, _) => builder.tuple_shim(tys),
+        _ => {
+            bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty);
+        }
+    };
+
+    builder.into_mir()
+}
+
+struct CloneShimBuilder<'a, 'tcx: 'a> {
+    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
+    blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+    span: Span,
+    sig: ty::FnSig<'tcx>,
+}
+
+impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
+    fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Self {
+        let sig = tcx.fn_sig(def_id);
+        let sig = tcx.erase_late_bound_regions(&sig);
+        let span = tcx.def_span(def_id);
+
+        CloneShimBuilder {
+            tcx,
+            def_id,
+            local_decls: local_decls_for_sig(&sig, span),
+            blocks: IndexVec::new(),
+            span,
+            sig,
+        }
+    }
+
+    fn into_mir(self) -> Mir<'tcx> {
+        Mir::new(
+            self.blocks,
+            IndexVec::from_elem_n(
+                VisibilityScopeData { span: self.span, parent_scope: None }, 1
+            ),
+            IndexVec::new(),
+            self.sig.output(),
+            self.local_decls,
+            self.sig.inputs().len(),
+            vec![],
+            self.span
+        )
+    }
+
+    fn source_info(&self) -> SourceInfo {
+        SourceInfo { span: self.span, scope: ARGUMENT_VISIBILITY_SCOPE }
+    }
+
+    fn block(
+        &mut self,
+        statements: Vec<Statement<'tcx>>,
+        kind: TerminatorKind<'tcx>,
+        is_cleanup: bool
+    ) -> BasicBlock {
+        let source_info = self.source_info();
+        self.blocks.push(BasicBlockData {
+            statements,
+            terminator: Some(Terminator { source_info, kind }),
+            is_cleanup,
+        })
+    }
+
+    fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
+        Statement {
+            source_info: self.source_info(),
+            kind,
+        }
+    }
+
+    fn copy_shim(&mut self) {
+        let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+        let ret_statement = self.make_statement(
+            StatementKind::Assign(
+                Lvalue::Local(RETURN_POINTER),
+                Rvalue::Use(Operand::Consume(rcvr))
+            )
+        );
+        self.block(vec![ret_statement], TerminatorKind::Return, false);
+    }
+
+    fn make_lvalue(&mut self, mutability: Mutability, ty: ty::Ty<'tcx>) -> Lvalue<'tcx> {
+        let span = self.span;
+        Lvalue::Local(
+            self.local_decls.push(temp_decl(mutability, ty, span))
+        )
+    }
+
+    fn make_clone_call(
+        &mut self,
+        ty: ty::Ty<'tcx>,
+        rcvr_field: Lvalue<'tcx>,
+        next: BasicBlock,
+        cleanup: BasicBlock
+    ) -> Lvalue<'tcx> {
+        let tcx = self.tcx;
+
+        let substs = Substs::for_item(
+            tcx,
+            self.def_id,
+            |_, _| tcx.types.re_erased,
+            |_, _| ty
+        );
+
+        // `func == Clone::clone(&ty) -> ty`
+        let func = Operand::Constant(box Constant {
+            span: self.span,
+            ty: tcx.mk_fn_def(self.def_id, substs),
+            literal: Literal::Value {
+                value: ConstVal::Function(self.def_id, substs),
+            },
+        });
+
+        let ref_loc = self.make_lvalue(
+            Mutability::Not,
+            tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
+                ty,
+                mutbl: hir::Mutability::MutImmutable,
+            })
+        );
+
+        let loc = self.make_lvalue(Mutability::Not, ty);
+
+        // `let ref_loc: &ty = &rcvr_field;`
+        let statement = self.make_statement(
+            StatementKind::Assign(
+                ref_loc.clone(),
+                Rvalue::Ref(tcx.types.re_erased, BorrowKind::Shared, rcvr_field)
+            )
+        );
+
+        // `let loc = Clone::clone(ref_loc);`
+        self.block(vec![statement], TerminatorKind::Call {
+            func,
+            args: vec![Operand::Consume(ref_loc)],
+            destination: Some((loc.clone(), next)),
+            cleanup: Some(cleanup),
+        }, false);
+
+        loc
+    }
+
+    fn loop_header(
+        &mut self,
+        beg: Lvalue<'tcx>,
+        end: Lvalue<'tcx>,
+        loop_body: BasicBlock,
+        loop_end: BasicBlock,
+        is_cleanup: bool
+    ) {
+        let tcx = self.tcx;
+
+        let cond = self.make_lvalue(Mutability::Mut, tcx.types.bool);
+        let compute_cond = self.make_statement(
+            StatementKind::Assign(
+                cond.clone(),
+                Rvalue::BinaryOp(BinOp::Ne, Operand::Consume(end), Operand::Consume(beg))
+            )
+        );
+
+        // `if end != beg { goto loop_body; } else { goto loop_end; }`
+        self.block(
+            vec![compute_cond],
+            TerminatorKind::if_(tcx, Operand::Consume(cond), loop_body, loop_end),
+            is_cleanup
+        );
+    }
+
+    fn make_usize(&self, value: usize) -> Box<Constant<'tcx>> {
+        let value = ConstUsize::new(value as u64, self.tcx.sess.target.uint_type).unwrap();
+        box Constant {
+            span: self.span,
+            ty: self.tcx.types.usize,
+            literal: Literal::Value {
+                value: ConstVal::Integral(ConstInt::Usize(value))
+            }
+        }
+    }
+
+    fn array_shim(&mut self, ty: ty::Ty<'tcx>, len: usize) {
+        let tcx = self.tcx;
+        let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+
+        let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize);
+        let end = self.make_lvalue(Mutability::Not, tcx.types.usize);
+        let ret = self.make_lvalue(Mutability::Mut, tcx.mk_array(ty, len));
+
+        // BB #0
+        // `let mut beg = 0;`
+        // `let end = len;`
+        // `goto #1;`
+        let inits = vec![
+            self.make_statement(
+                StatementKind::Assign(
+                    beg.clone(),
+                    Rvalue::Use(Operand::Constant(self.make_usize(0)))
+                )
+            ),
+            self.make_statement(
+                StatementKind::Assign(
+                    end.clone(),
+                    Rvalue::Use(Operand::Constant(self.make_usize(len)))
+                )
+            )
+        ];
+        self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
+
+        // BB #1: loop {
+        //     BB #2;
+        //     BB #3;
+        // }
+        // BB #4;
+        self.loop_header(beg.clone(), end, BasicBlock::new(2), BasicBlock::new(4), false);
+
+        // BB #2
+        // `let cloned = Clone::clone(rcvr[beg])`;
+        // Goto #3 if ok, #5 if unwinding happens.
+        let rcvr_field = rcvr.clone().index(Operand::Consume(beg.clone()));
+        let cloned = self.make_clone_call(ty, rcvr_field, BasicBlock::new(3), BasicBlock::new(5));
+
+        // BB #3
+        // `ret[beg] = cloned;`
+        // `beg = beg + 1;`
+        // `goto #1`;
+        let ret_field = ret.clone().index(Operand::Consume(beg.clone()));
+        let statements = vec![
+            self.make_statement(
+                StatementKind::Assign(
+                    ret_field,
+                    Rvalue::Use(Operand::Consume(cloned))
+                )
+            ),
+            self.make_statement(
+                StatementKind::Assign(
+                    beg.clone(),
+                    Rvalue::BinaryOp(
+                        BinOp::Add,
+                        Operand::Consume(beg.clone()),
+                        Operand::Constant(self.make_usize(1))
+                    )
+                )
+            )
+        ];
+        self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false);
+
+        // BB #4
+        // `return ret;`
+        let ret_statement = self.make_statement(
+            StatementKind::Assign(
+                Lvalue::Local(RETURN_POINTER),
+                Rvalue::Use(Operand::Consume(ret.clone())),
+            )
+        );
+        self.block(vec![ret_statement], TerminatorKind::Return, false);
+
+        // BB #5 (cleanup)
+        // `let end = beg;`
+        // `let mut beg = 0;`
+        // goto #6;
+        let end = beg;
+        let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize);
+        let init = self.make_statement(
+            StatementKind::Assign(
+                beg.clone(),
+                Rvalue::Use(Operand::Constant(self.make_usize(0)))
+            )
+        );
+        self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
+
+        // BB #6 (cleanup): loop {
+        //     BB #7;
+        //     BB #8;
+        // }
+        // BB #9;
+        self.loop_header(beg.clone(), end, BasicBlock::new(7), BasicBlock::new(9), true);
+
+        // BB #7 (cleanup)
+        // `drop(ret[beg])`;
+        self.block(vec![], TerminatorKind::Drop {
+            location: ret.index(Operand::Consume(beg.clone())),
+            target: BasicBlock::new(8),
+            unwind: None,
+        }, true);
+
+        // BB #8 (cleanup)
+        // `beg = beg + 1;`
+        // `goto #6;`
+        let statement = self.make_statement(
+            StatementKind::Assign(
+                beg.clone(),
+                Rvalue::BinaryOp(
+                    BinOp::Add,
+                    Operand::Consume(beg.clone()),
+                    Operand::Constant(self.make_usize(1))
+                )
+            )
+        );
+        self.block(vec![statement], TerminatorKind::Goto { target: BasicBlock::new(6) }, true);
+
+        // BB #9 (resume)
+        self.block(vec![], TerminatorKind::Resume, true);
+    }
+
+    fn tuple_shim(&mut self, tys: &ty::Slice<ty::Ty<'tcx>>) {
+        let rcvr = Lvalue::Local(Local::new(1+0)).deref();
+
+        let mut returns = Vec::new();
+        for (i, ity) in tys.iter().enumerate() {
+            let rcvr_field = rcvr.clone().field(Field::new(i), *ity);
+
+            // BB #(2i)
+            // `returns[i] = Clone::clone(&rcvr.i);`
+            // Goto #(2i + 2) if ok, #(2i + 1) if unwinding happens.
+            returns.push(
+                self.make_clone_call(
+                    *ity,
+                    rcvr_field,
+                    BasicBlock::new(2 * i + 2),
+                    BasicBlock::new(2 * i + 1),
+                )
+            );
+
+            // BB #(2i + 1) (cleanup)
+            if i == 0 {
+                // Nothing to drop, just resume.
+                self.block(vec![], TerminatorKind::Resume, true);
+            } else {
+                // Drop previous field and goto previous cleanup block.
+                self.block(vec![], TerminatorKind::Drop {
+                    location: returns[i - 1].clone(),
+                    target: BasicBlock::new(2 * i - 1),
+                    unwind: None,
+                }, true);
+            }
+        }
+
+        // `return (returns[0], returns[1], ..., returns[tys.len() - 1]);`
+        let ret_statement = self.make_statement(
+            StatementKind::Assign(
+                Lvalue::Local(RETURN_POINTER),
+                Rvalue::Aggregate(
+                    box AggregateKind::Tuple,
+                    returns.into_iter().map(Operand::Consume).collect()
+                )
+            )
+        );
+       self.block(vec![ret_statement], TerminatorKind::Return, false);
+    }
+}
+
 /// Build a "call" shim for `def_id`. The shim calls the
 /// function specified by `call_kind`, first adjusting its first
 /// argument according to `rcvr_adjustment`.
@@ -303,7 +683,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                 span
             ));
             statements.push(Statement {
-                source_info: source_info,
+                source_info,
                 kind: StatementKind::Assign(
                     Lvalue::Local(ref_rcvr),
                     Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l)
@@ -317,7 +697,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
         CallKind::Indirect => (rcvr, vec![]),
         CallKind::Direct(def_id) => (
             Operand::Constant(box Constant {
-                span: span,
+                span,
                 ty: tcx.type_of(def_id),
                 literal: Literal::Value {
                     value: ConstVal::Function(def_id,
@@ -351,7 +731,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     // BB #0
     block(&mut blocks, statements, TerminatorKind::Call {
         func: callee,
-        args: args,
+        args,
         destination: Some((Lvalue::Local(RETURN_POINTER),
                            BasicBlock::new(1))),
         cleanup: if let Adjustment::RefMut = rcvr_adjustment {
@@ -423,7 +803,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     let local_decls = local_decls_for_sig(&sig, span);
 
     let source_info = SourceInfo {
-        span: span,
+        span,
         scope: ARGUMENT_VISIBILITY_SCOPE
     };
 
@@ -436,7 +816,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     // return = ADT(arg0, arg1, ...); return
     let start_block = BasicBlockData {
         statements: vec![Statement {
-            source_info: source_info,
+            source_info,
             kind: StatementKind::Assign(
                 Lvalue::Local(RETURN_POINTER),
                 Rvalue::Aggregate(
@@ -448,7 +828,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
             )
         }],
         terminator: Some(Terminator {
-            source_info: source_info,
+            source_info,
             kind: TerminatorKind::Return,
         }),
         is_cleanup: false
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index 23a9c4c57ca..3f14a6be8b2 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -75,7 +75,7 @@ impl AddCallGuards {
                         statements: vec![],
                         is_cleanup: block.is_cleanup,
                         terminator: Some(Terminator {
-                            source_info: source_info,
+                            source_info,
                             kind: TerminatorKind::Goto { target: *destination }
                         })
                     };
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index dec0717e9e3..59b81f7e77c 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -299,8 +299,8 @@ impl<'tcx> ConstantPropagationVisitor<'tcx> {
     fn new(dest_local: Local, constant: Constant<'tcx>)
            -> ConstantPropagationVisitor<'tcx> {
         ConstantPropagationVisitor {
-            dest_local: dest_local,
-            constant: constant,
+            dest_local,
+            constant,
             uses_replaced: 0,
         }
     }
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index b158cb43ce7..97391452e59 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -50,8 +50,8 @@ impl MirPass for ElaborateDrops {
         let elaborate_patch = {
             let mir = &*mir;
             let env = MoveDataParamEnv {
-                move_data: move_data,
-                param_env: param_env
+                move_data,
+                param_env,
             };
             let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
             let flow_inits =
@@ -64,11 +64,11 @@ impl MirPass for ElaborateDrops {
                                       |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
-                tcx: tcx,
-                mir: mir,
+                tcx,
+                mir,
                 env: &env,
-                flow_inits: flow_inits,
-                flow_uninits: flow_uninits,
+                flow_inits,
+                flow_uninits,
                 drop_flags: FxHashMap(),
                 patch: MirPatch::new(mir),
             }.elaborate()
@@ -510,7 +510,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent);
                 self.patch.patch_terminator(bb, TerminatorKind::Drop {
                     location: location.clone(),
-                    target: target,
+                    target,
                     unwind: Some(unwind)
                 });
             }
@@ -519,7 +519,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
-            span: span,
+            span,
             ty: self.tcx.types.bool,
             literal: Literal::Value { value: ConstVal::Bool(val) }
         })))
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 89de847231c..fa51cd91be1 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -28,7 +28,7 @@ struct EraseRegionsVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         EraseRegionsVisitor {
-            tcx: tcx,
+            tcx,
             in_validation_statement: false,
         }
     }
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index d3fee8045e6..53b46dd2683 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -90,8 +90,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
                         callsites.push_back(CallSite {
                             callee: callee_def_id,
-                            substs: substs,
-                            bb: bb,
+                            substs,
+                            bb,
                             location: terminator.source_info
                         });
                     }
@@ -115,8 +115,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
                         callee_mir.subst(self.tcx, callsite.substs)
                     }
+                    Ok(_) => continue,
 
-                    _ => continue,
+                    Err(mut bug) => {
+                        // FIXME(#43542) shouldn't have to cancel an error
+                        bug.cancel();
+                        continue
+                    }
                 };
 
                 let start = caller_mir.basic_blocks().len();
@@ -136,8 +141,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                             if callsite.callee != callee_def_id {
                                 callsites.push_back(CallSite {
                                     callee: callee_def_id,
-                                    substs: substs,
-                                    bb: bb,
+                                    substs,
+                                    bb,
                                     location: terminator.source_info
                                 });
                             }
@@ -433,12 +438,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                 let mut integrator = Integrator {
                     block_idx: bb_len,
                     args: &args,
-                    local_map: local_map,
-                    scope_map: scope_map,
-                    promoted_map: promoted_map,
+                    local_map,
+                    scope_map,
+                    promoted_map,
                     _callsite: callsite,
                     destination: dest,
-                    return_block: return_block,
+                    return_block,
                     cleanup_block: cleanup,
                     in_cleanup_block: false
                 };
@@ -461,7 +466,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             kind => {
                 caller_mir[callsite.bb].terminator = Some(Terminator {
                     source_info: terminator.source_info,
-                    kind: kind
+                    kind,
                 });
                 false
             }
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 88a368077d4..6ccc886577a 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -76,8 +76,8 @@ struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
 impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
     fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> {
         OptimizationFinder {
-            mir: mir,
-            tcx: tcx,
+            mir,
+            tcx,
             optimizations: OptimizationList::default(),
         }
     }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index a247ce2231e..d8dffa03662 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -93,7 +93,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum)
         }
     }
     tcx.hir.krate().visit_all_item_likes(&mut GatherCtors {
-        tcx: tcx,
+        tcx,
         set: &mut set,
     }.as_deep_visitor());
 
@@ -122,8 +122,9 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
 }
 
 fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> {
-    // Borrowck uses `mir_validated`, so we have to force it to
+    // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
     // execute before we can steal.
+    ty::queries::mir_borrowck::force(tcx, DUMMY_SP, def_id);
     ty::queries::borrowck::force(tcx, DUMMY_SP, def_id);
 
     let mut mir = tcx.mir_validated(def_id).steal();
@@ -148,6 +149,14 @@ fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         pass.run_pass(tcx, source, mir);
 
+        for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() {
+            let promoted_source = MirSource::Promoted(source.item_id(), index);
+            pass.run_pass(tcx, promoted_source, promoted_mir);
+
+            // Let's make sure we don't miss any nested instances
+            assert!(promoted_mir.promoted.is_empty());
+        }
+
         for hook in tcx.mir_passes.hooks() {
             hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
         }
diff --git a/src/librustc_mir/transform/nll.rs b/src/librustc_mir/transform/nll.rs
index fb4764c4962..bd02788df16 100644
--- a/src/librustc_mir/transform/nll.rs
+++ b/src/librustc_mir/transform/nll.rs
@@ -27,7 +27,7 @@ struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
     pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
         NLLVisitor {
-            infcx: infcx,
+            infcx,
             lookup_map: HashMap::new(),
         }
     }
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index e1c4602b045..1665cb2f15e 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -107,7 +107,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
                     LvalueContext::Store |
                     LvalueContext::Call => {
                         *temp = TempState::Defined {
-                            location: location,
+                            location,
                             uses: 0
                         };
                         return;
@@ -140,7 +140,7 @@ pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Local, T
     let mut collector = TempCollector {
         temps: IndexVec::from_elem(TempState::Undefined, &mir.local_decls),
         span: mir.span,
-        mir: mir,
+        mir,
     };
     for (bb, data) in rpo {
         collector.visit_basic_block_data(bb, data);
@@ -165,7 +165,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             statements: vec![],
             terminator: Some(Terminator {
                 source_info: SourceInfo {
-                    span: span,
+                    span,
                     scope: ARGUMENT_VISIBILITY_SCOPE
                 },
                 kind: TerminatorKind::Return
@@ -179,7 +179,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
         let data = &mut self.promoted[last];
         data.statements.push(Statement {
             source_info: SourceInfo {
-                span: span,
+                span,
                 scope: ARGUMENT_VISIBILITY_SCOPE
             },
             kind: StatementKind::Assign(Lvalue::Local(dest), rvalue)
@@ -251,7 +251,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                 Terminator {
                     source_info: terminator.source_info,
                     kind: mem::replace(&mut terminator.kind, TerminatorKind::Goto {
-                        target: target
+                        target,
                     })
                 }
             };
@@ -268,8 +268,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
 
                     *self.promoted[last].terminator_mut() = Terminator {
                         kind: TerminatorKind::Call {
-                            func: func,
-                            args: args,
+                            func,
+                            args,
                             cleanup: None,
                             destination: Some((Lvalue::Local(new_temp), new_target))
                         },
@@ -289,7 +289,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
     fn promote_candidate(mut self, candidate: Candidate) {
         let span = self.promoted.span;
         let new_operand = Operand::Constant(box Constant {
-            span: span,
+            span,
             ty: self.promoted.return_ty,
             literal: Literal::Promoted {
                 index: Promoted::new(self.source.promoted.len())
@@ -387,7 +387,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
             promoted: Mir::new(
                 IndexVec::new(),
                 Some(VisibilityScopeData {
-                    span: span,
+                    span,
                     parent_scope: None
                 }).into_iter().collect(),
                 IndexVec::new(),
@@ -423,7 +423,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
             TerminatorKind::Drop { location: Lvalue::Local(index), target, .. } => {
                 if promoted(index) {
                     terminator.kind = TerminatorKind::Goto {
-                        target: target
+                        target,
                     };
                 }
             }
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 2ecffdf9fdf..ee99bb7d9d5 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -135,13 +135,13 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
         let temps = promote_consts::collect_temps(mir, &mut rpo);
         rpo.reset();
         Qualifier {
-            mode: mode,
+            mode,
             span: mir.span,
-            def_id: def_id,
-            mir: mir,
-            rpo: rpo,
-            tcx: tcx,
-            param_env: param_env,
+            def_id,
+            mir,
+            rpo,
+            tcx,
+            param_env,
             temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
             return_qualif: None,
             qualif: Qualif::empty(),
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 268e7a4c185..ceff52409b2 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -13,7 +13,7 @@ use syntax::ast;
 use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
-use rustc::mir::{self, Mir};
+use rustc::mir::{self, Mir, Location};
 use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
@@ -202,7 +202,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // reset GEN and KILL sets before emulating their effect.
         for e in sets.gen_set.words_mut() { *e = 0; }
         for e in sets.kill_set.words_mut() { *e = 0; }
-        results.0.operator.statement_effect(&mut sets, bb, j);
+        results.0.operator.statement_effect(&mut sets, Location { block: bb, statement_index: j });
         sets.on_entry.union(sets.gen_set);
         sets.on_entry.subtract(sets.kill_set);
     }
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index a1d56ccd874..070250cda4d 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -99,8 +99,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
         let basic_blocks = mir.basic_blocks_mut();
 
         CfgSimplifier {
-            basic_blocks: basic_blocks,
-            pred_count: pred_count
+            basic_blocks,
+            pred_count,
         }
     }
 
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index f3a82b54063..72092042f8d 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -108,8 +108,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
 impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
     fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
         TypeVerifier {
-            cx: cx,
-            mir: mir,
+            cx,
+            mir,
             last_span: mir.span,
             errors_reported: false
         }
@@ -235,8 +235,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                             }
                         } else {
                             LvalueTy::Downcast {
-                                adt_def: adt_def,
-                                substs: substs,
+                                adt_def,
+                                substs,
                                 variant_index: index
                             }
                         }
@@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
            param_env: ty::ParamEnv<'gcx>)
            -> Self {
         TypeChecker {
-            infcx: infcx,
+            infcx,
             fulfillment_cx: traits::FulfillmentContext::new(),
             last_span: DUMMY_SP,
             body_id,
@@ -740,12 +740,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
 pub struct TypeckMir;
 
-impl TypeckMir {
-    pub fn new() -> Self {
-        TypeckMir
-    }
-}
-
 impl MirPass for TypeckMir {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
new file mode 100644
index 00000000000..9de30726586
--- /dev/null
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -0,0 +1,192 @@
+// Copyright 2012-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.
+
+use rustc::ty::{self, TyCtxt};
+use rustc_errors::DiagnosticBuilder;
+use syntax_pos::{MultiSpan, Span};
+
+use std::fmt;
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum Origin { Ast, Mir }
+
+impl fmt::Display for Origin {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Origin::Mir => write!(w, " (Mir)"),
+            Origin::Ast => ty::tls::with_opt(|opt_tcx| {
+                // If user passed `-Z borrowck-mir`, then include an
+                // AST origin as part of the error report
+                if let Some(tcx) = opt_tcx {
+                    if tcx.sess.opts.debugging_opts.borrowck_mir {
+                        return write!(w, " (Ast)");
+                    }
+                }
+                // otherwise, do not include the origin (i.e., print
+                // nothing at all)
+                Ok(())
+            }),
+        }
+    }
+}
+
+pub trait BorrowckErrors {
+    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
+                                                         sp: S,
+                                                         msg: &str,
+                                                         code: &str)
+                                                         -> DiagnosticBuilder<'a>;
+
+    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
+                                               sp: S,
+                                               msg: &str)
+                                               -> DiagnosticBuilder<'a>;
+
+    fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
+                                 -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0505,
+                         "cannot move out of `{}` because it is borrowed{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_use_when_mutably_borrowed(&self, span: Span, desc: &str, o: Origin)
+                                        -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0503,
+                         "cannot use `{}` because it was mutably borrowed{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_act_on_uninitialized_variable(&self,
+                                            span: Span,
+                                            verb: &str,
+                                            desc: &str,
+                                            o: Origin)
+                                            -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0381,
+                         "{} of possibly uninitialized variable: `{}`{OGN}",
+                         verb, desc, OGN=o)
+    }
+
+    fn cannot_mutably_borrow_multiply(&self,
+                                      span: Span,
+                                      desc: &str,
+                                      opt_via: &str,
+                                      o: Origin)
+                                      -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0499,
+                         "cannot borrow `{}`{} as mutable more than once at a time{OGN}",
+                         desc, opt_via, OGN=o)
+    }
+
+    fn cannot_uniquely_borrow_by_two_closures(&self, span: Span, desc: &str, o: Origin)
+                                              -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0524,
+                         "two closures require unique access to `{}` at the same time{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_uniquely_borrow_by_one_closure(&self,
+                                             span: Span,
+                                             desc_new: &str,
+                                             noun_old: &str,
+                                             msg_old: &str,
+                                             o: Origin)
+                                             -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0500,
+                         "closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
+                         desc_new, noun_old, msg_old, OGN=o)
+    }
+
+    fn cannot_reborrow_already_uniquely_borrowed(&self,
+                                                 span: Span,
+                                                 desc_new: &str,
+                                                 msg_new: &str,
+                                                 kind_new: &str,
+                                                 o: Origin)
+                                                 -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0501,
+                         "cannot borrow `{}`{} as {} because previous closure \
+                          requires unique access{OGN}",
+                         desc_new, msg_new, kind_new, OGN=o)
+    }
+
+    fn cannot_reborrow_already_borrowed(&self,
+                                        span: Span,
+                                        desc_new: &str,
+                                        msg_new: &str,
+                                        kind_new: &str,
+                                        noun_old: &str,
+                                        kind_old: &str,
+                                        msg_old: &str,
+                                        o: Origin)
+                                        -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0502,
+                         "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
+                         desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o)
+    }
+
+    fn cannot_assign_to_borrowed(&self, span: Span, desc: &str, o: Origin)
+                                 -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0506,
+                         "cannot assign to `{}` because it is borrowed{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
+                                -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0504,
+                         "cannot move `{}` into closure because it is borrowed{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin)
+                                 -> DiagnosticBuilder
+    {
+        struct_span_err!(self, span, E0384,
+                         "re-assignment of immutable variable `{}`{OGN}",
+                         desc, OGN=o)
+    }
+
+    fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
+                            -> DiagnosticBuilder
+    {
+        self.struct_span_err(span, &format!("cannot assign to immutable static item {}{OGN}",
+                                            desc, OGN=o))
+    }
+}
+
+impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> {
+    fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
+                                                         sp: S,
+                                                         msg: &str,
+                                                         code: &str)
+                                                         -> DiagnosticBuilder<'a>
+    {
+        self.sess.struct_span_err_with_code(sp, msg, code)
+    }
+
+    fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
+                                               sp: S,
+                                               msg: &str)
+                                               -> DiagnosticBuilder<'a>
+    {
+        self.sess.struct_span_err(sp, msg)
+    }
+}
diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs
index d20d50c5611..8263e149d84 100644
--- a/src/librustc_mir/util/def_use.rs
+++ b/src/librustc_mir/util/def_use.rs
@@ -50,10 +50,6 @@ impl<'tcx> DefUseAnalysis<'tcx> {
         &self.info[local]
     }
 
-    pub fn local_info_mut(&mut self, local: Local) -> &mut Info<'tcx> {
-        &mut self.info[local]
-    }
-
     fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F)
                                where F: for<'a> FnMut(&'a mut Lvalue<'tcx>,
                                                       LvalueContext<'tcx>,
@@ -97,8 +93,8 @@ impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> {
                     location: Location) {
         if let Some(ref mut info) = self.lvalue_mut_info(lvalue) {
             info.defs_and_uses.push(Use {
-                context: context,
-                location: location,
+                context,
+                location,
             })
         }
         self.super_lvalue(lvalue, context, location)
@@ -140,8 +136,8 @@ impl<'tcx, F> MutateUseVisitor<'tcx, F> {
            -> MutateUseVisitor<'tcx, F>
            where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) {
         MutateUseVisitor {
-            query: query,
-            callback: callback,
+            query,
+            callback,
             phantom: PhantomData,
         }
     }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index da7e218439c..d8a061f4b19 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -521,7 +521,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
 
         let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
-            ty: ty,
+            ty,
             mutbl: hir::Mutability::MutMutable
         });
         let ref_lvalue = self.new_temp(ref_ty);
@@ -860,7 +860,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
     fn drop_block<'a>(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
         let block = TerminatorKind::Drop {
             location: self.lvalue.clone(),
-            target: target,
+            target,
             unwind: unwind.into_option()
         };
         self.new_block(unwind, block)
diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs
index 4386bab38c0..f0d837e1362 100644
--- a/src/librustc_mir/util/mod.rs
+++ b/src/librustc_mir/util/mod.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub mod borrowck_errors;
 pub mod elaborate_drops;
 pub mod def_use;
 pub mod patch;
diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs
index ac121131eb9..1af0b6c67f2 100644
--- a/src/librustc_mir/util/patch.rs
+++ b/src/librustc_mir/util/patch.rs
@@ -156,7 +156,7 @@ impl<'tcx> MirPatch<'tcx> {
             );
             mir[loc.block].statements.insert(
                 loc.statement_index, Statement {
-                    source_info: source_info,
+                    source_info,
                     kind: stmt
                 });
             delta += 1;
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index b22f8112d7a..ffe444933a3 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -140,14 +140,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             ExprKind::Continue(Some(ident)) => {
                 self.check_label(ident.node, ident.span);
             }
-            ExprKind::MethodCall(ref segment, ..) => {
-                if let Some(ref params) = segment.parameters {
-                    if let PathParameters::Parenthesized(..) = **params {
-                        self.err_handler().span_err(expr.span,
-                            "parenthesized parameters cannot be used on method calls");
-                    }
-                }
-            }
             _ => {}
         }
 
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 9185f73974c..763f885b4d0 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -470,7 +470,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.hir.krate().visit_all_item_likes(&mut CheckCrateVisitor {
-        tcx: tcx,
+        tcx,
         tables: &ty::TypeckTables::empty(None),
         in_fn: false,
         promotable: false,
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index ed5ea69d04e..28b99e1185b 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_passes"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -36,13 +33,13 @@ extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 
-pub mod diagnostics;
+mod diagnostics;
 
 pub mod ast_validation;
 pub mod consts;
 pub mod hir_stats;
 pub mod loops;
-pub mod mir_stats;
+mod mir_stats;
 pub mod no_asm;
 pub mod static_recursion;
 
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index 21a4c007fb1..1b2a07cd1a7 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -51,7 +51,7 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
 pub fn check_crate(sess: &Session, map: &Map) {
     let krate = map.krate();
     krate.visit_all_item_likes(&mut CheckLoopVisitor {
-        sess: sess,
+        sess,
         hir_map: map,
         cx: Normal,
     }.as_deep_visitor());
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index d5e477ff0c7..9975082c551 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -13,7 +13,6 @@
 // completely accurate (some things might be counted twice, others missed).
 
 use rustc_const_math::{ConstUsize};
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::middle::const_val::{ConstVal};
 use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData};
 use rustc::mir::{Constant, Literal, Location, LocalDecl};
@@ -22,9 +21,7 @@ use rustc::mir::{Mir, Operand, ProjectionElem};
 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
 use rustc::mir::visit as mir_visit;
-use rustc::mir::visit::Visitor;
 use rustc::ty::{ClosureSubsts, TyCtxt};
-use rustc::util::common::to_readable_str;
 use rustc::util::nodemap::{FxHashMap};
 
 struct NodeData {
@@ -37,21 +34,6 @@ struct StatCollector<'a, 'tcx: 'a> {
     data: FxHashMap<&'static str, NodeData>,
 }
 
-pub fn print_mir_stats<'tcx, 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, title: &str) {
-    let mut collector = StatCollector {
-        _tcx: tcx,
-        data: FxHashMap(),
-    };
-    // For debugging instrumentation like this, we don't need to worry
-    // about maintaining the dep graph.
-    let _ignore = tcx.dep_graph.in_ignore();
-    for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
-        let mir = tcx.optimized_mir(def_id);
-        collector.visit_mir(&mir);
-    }
-    collector.print(title);
-}
-
 impl<'a, 'tcx> StatCollector<'a, 'tcx> {
 
     fn record_with_size(&mut self, label: &'static str, node_size: usize) {
@@ -67,27 +49,6 @@ impl<'a, 'tcx> StatCollector<'a, 'tcx> {
     fn record<T>(&mut self, label: &'static str, node: &T) {
         self.record_with_size(label, ::std::mem::size_of_val(node));
     }
-
-    fn print(&self, title: &str) {
-        let mut stats: Vec<_> = self.data.iter().collect();
-
-        stats.sort_by_key(|&(_, ref d)| d.count * d.size);
-
-        println!("\n{}\n", title);
-
-        println!("{:<32}{:>18}{:>14}{:>14}",
-            "Name", "Accumulated Size", "Count", "Item Size");
-        println!("------------------------------------------------------------------------------");
-
-        for (label, data) in stats {
-            println!("{:<32}{:>18}{:>14}{:>14}",
-                label,
-                to_readable_str(data.count * data.size),
-                to_readable_str(data.count),
-                to_readable_str(data.size));
-        }
-        println!("------------------------------------------------------------------------------");
-    }
 }
 
 impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
index 0dbb2d1d4d0..987243b5234 100644
--- a/src/librustc_passes/static_recursion.rs
+++ b/src/librustc_passes/static_recursion.rs
@@ -91,8 +91,8 @@ pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>)
                          -> Result<(), ErrorReported>
 {
     let mut visitor = CheckCrateVisitor {
-        sess: sess,
-        hir_map: hir_map,
+        sess,
+        hir_map,
         discriminant_map: NodeMap(),
         detected_recursive_ids: NodeSet(),
     };
diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs
index ef1d9093df2..4cc65ee28e8 100644
--- a/src/librustc_platform_intrinsics/lib.rs
+++ b/src/librustc_platform_intrinsics/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_platform_intrinsics"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![deny(warnings)]
 #![allow(bad_style)]
 
diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs
index b38369665f8..1a2e8e9c5d8 100644
--- a/src/librustc_platform_intrinsics/powerpc.rs
+++ b/src/librustc_platform_intrinsics/powerpc.rs
@@ -282,6 +282,61 @@ pub fn find(name: &str) -> Option<Intrinsic> {
             output: &::U32x4,
             definition: Named("llvm.ppc.altivec.vavguw")
         },
+        "_vec_packssh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::I8x16,
+            definition: Named("llvm.ppc.altivec.vpkshss")
+        },
+        "_vec_packsuh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS },
+            output: &::U8x16,
+            definition: Named("llvm.ppc.altivec.vpkuhus")
+        },
+        "_vec_packssw" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vpkswss")
+        },
+        "_vec_packsuw" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vpkuwus")
+        },
+        "_vec_packsush" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS },
+            output: &::U8x16,
+            definition: Named("llvm.ppc.altivec.vpkshus")
+        },
+        "_vec_packsusw" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::U16x8,
+            definition: Named("llvm.ppc.altivec.vpkswus")
+        },
+        "_vec_packpx" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vpkpx")
+        },
+        "_vec_unpacklsb" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vupklsb")
+        },
+        "_vec_unpacklsh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vupklsh")
+        },
+        "_vec_unpackhsb" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS },
+            output: &::I16x8,
+            definition: Named("llvm.ppc.altivec.vupkhsb")
+        },
+        "_vec_unpackhsh" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS },
+            output: &::I32x4,
+            definition: Named("llvm.ppc.altivec.vupkhsh")
+        },
         _ => return None,
     })
 }
diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs
index e17a3c82b50..a2a6d183e9c 100644
--- a/src/librustc_plugin/lib.rs
+++ b/src/librustc_plugin/lib.rs
@@ -60,15 +60,13 @@
 //! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of
 //! the Unstable Book for more examples.
 
-#![crate_name = "rustc_plugin"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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(rustc_diagnostic_macros)]
+#![feature(staged_api)]
 
 #[macro_use] extern crate syntax;
 
@@ -80,7 +78,7 @@ extern crate rustc_errors as errors;
 
 pub use self::registry::Registry;
 
-pub mod diagnostics;
+mod diagnostics;
 pub mod registry;
 pub mod load;
 pub mod build;
diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs
index ed49e8a14c8..aba56788928 100644
--- a/src/librustc_plugin/load.rs
+++ b/src/librustc_plugin/load.rs
@@ -91,7 +91,7 @@ pub fn load_plugins(sess: &Session,
 impl<'a> PluginLoader<'a> {
     fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
         PluginLoader {
-            sess: sess,
+            sess,
             reader: CrateLoader::new(sess, cstore, crate_name),
             plugins: vec![],
         }
@@ -104,8 +104,8 @@ impl<'a> PluginLoader<'a> {
             let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
             let fun = self.dylink_registrar(span, lib, symbol);
             self.plugins.push(PluginRegistrar {
-                fun: fun,
-                args: args,
+                fun,
+                args,
             });
         }
     }
diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs
index aac21f2af0d..3f74093241d 100644
--- a/src/librustc_plugin/registry.rs
+++ b/src/librustc_plugin/registry.rs
@@ -67,9 +67,9 @@ impl<'a> Registry<'a> {
     #[doc(hidden)]
     pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
         Registry {
-            sess: sess,
+            sess,
             args_hidden: None,
-            krate_span: krate_span,
+            krate_span,
             syntax_exts: vec![],
             early_lint_passes: vec![],
             late_lint_passes: vec![],
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 983f478e07d..772b16bbecf 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_privacy"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -41,7 +38,7 @@ use std::cmp;
 use std::mem::replace;
 use std::rc::Rc;
 
-pub mod diagnostics;
+mod diagnostics;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Visitor used to determine if pub(restricted) is used anywhere in the crate.
@@ -1496,9 +1493,9 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
             item_def_id: self.tcx.hir.local_def_id(item_id),
             span: self.tcx.hir.span(item_id),
             min_visibility: ty::Visibility::Public,
-            required_visibility: required_visibility,
+            required_visibility,
             has_pub_restricted: self.has_pub_restricted,
-            has_old_errors: has_old_errors,
+            has_old_errors,
         }
     }
 }
@@ -1660,7 +1657,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Check privacy of names not checked in previous compilation stages.
     let mut visitor = NamePrivacyVisitor {
-        tcx: tcx,
+        tcx,
         tables: &empty_tables,
         current_item: CRATE_NODE_ID,
         empty_tables: &empty_tables,
@@ -1670,7 +1667,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Check privacy of explicitly written types and traits as well as
     // inferred types of expressions and patterns.
     let mut visitor = TypePrivacyVisitor {
-        tcx: tcx,
+        tcx,
         tables: &empty_tables,
         current_item: DefId::local(CRATE_DEF_INDEX),
         span: krate.span,
@@ -1681,7 +1678,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Build up a set of all exported items in the AST. This is a set of all
     // items which are reachable from external crates based on visibility.
     let mut visitor = EmbargoVisitor {
-        tcx: tcx,
+        tcx,
         access_levels: Default::default(),
         prev_level: Some(AccessLevel::Public),
         changed: false,
@@ -1698,7 +1695,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     {
         let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
-            tcx: tcx,
+            tcx,
             access_levels: &visitor.access_levels,
             in_variant: false,
             old_error_set: NodeSet(),
@@ -1708,7 +1705,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         let has_pub_restricted = {
             let mut pub_restricted_visitor = PubRestrictedVisitor {
-                tcx: tcx,
+                tcx,
                 has_pub_restricted: false
             };
             intravisit::walk_crate(&mut pub_restricted_visitor, krate);
@@ -1717,8 +1714,8 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Check for private types and traits in public interfaces
         let mut visitor = PrivateItemsInPublicInterfacesVisitor {
-            tcx: tcx,
-            has_pub_restricted: has_pub_restricted,
+            tcx,
+            has_pub_restricted,
             old_error_set: &visitor.old_error_set,
             inner_visibility: ty::Visibility::Public,
         };
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a061484b5c4..47fa5357abf 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -172,7 +172,7 @@ impl<'a> Resolver<'a> {
 
                         let subclass = SingleImport {
                             target: binding,
-                            source: source,
+                            source,
                             result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
                             type_ns_only: false,
                         };
@@ -229,7 +229,7 @@ impl<'a> Resolver<'a> {
                                 target: rename,
                                 source: ident.node,
                                 result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
-                                type_ns_only: type_ns_only,
+                                type_ns_only,
                             };
                             let id = source_item.node.id;
                             self.add_import_directive(
@@ -239,7 +239,7 @@ impl<'a> Resolver<'a> {
                     }
                     ViewPathGlob(_) => {
                         let subclass = GlobImport {
-                            is_prelude: is_prelude,
+                            is_prelude,
                             max_vis: Cell::new(ty::Visibility::Invisible),
                         };
                         self.add_import_directive(
@@ -262,13 +262,13 @@ impl<'a> Resolver<'a> {
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
                     id: item.id,
-                    parent: parent,
+                    parent,
                     imported_module: Cell::new(Some(module)),
                     subclass: ImportDirectiveSubclass::ExternCrate,
                     span: item.span,
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
-                    expansion: expansion,
+                    expansion,
                     used: Cell::new(used),
                 });
                 self.potentially_unused_imports.push(directive);
@@ -618,10 +618,10 @@ impl<'a> Resolver<'a> {
             parent: graph_root,
             imported_module: Cell::new(Some(module)),
             subclass: ImportDirectiveSubclass::MacroUse,
-            span: span,
+            span,
             module_path: Vec::new(),
             vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
-            expansion: expansion,
+            expansion,
             used: Cell::new(false),
         });
 
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index a8bb6619bbd..a66d1ce0859 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -121,9 +121,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                  directive.vis.get() == ty::Visibility::Public ||
                  directive.span.source_equal(&DUMMY_SP) => {}
             ImportDirectiveSubclass::ExternCrate => {
-                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-                let msg = "unused extern crate";
-             ;   resolver.session.buffer_lint(lint, directive.id, directive.span, msg)
+                resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
             }
             ImportDirectiveSubclass::MacroUse => {
                 let lint = lint::builtin::UNUSED_IMPORTS;
@@ -135,7 +133,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
     }
 
     let mut visitor = UnusedImportCheckVisitor {
-        resolver: resolver,
+        resolver,
         unused_imports: NodeMap(),
     };
     visit::walk_crate(&mut visitor, krate);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index da170e7fe22..a83ac9bb633 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_resolve"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -581,6 +578,55 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
     }
 }
 
+struct UsePlacementFinder {
+    target_module: NodeId,
+    span: Option<Span>,
+    found_use: bool,
+}
+
+impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
+    fn visit_mod(
+        &mut self,
+        module: &'tcx ast::Mod,
+        _: Span,
+        _: &[ast::Attribute],
+        node_id: NodeId,
+    ) {
+        if self.span.is_some() {
+            return;
+        }
+        if node_id != self.target_module {
+            visit::walk_mod(self, module);
+            return;
+        }
+        // find a use statement
+        for item in &module.items {
+            match item.node {
+                ItemKind::Use(..) => {
+                    // don't suggest placing a use before the prelude
+                    // import or other generated ones
+                    if item.span == DUMMY_SP {
+                        let mut span = item.span;
+                        span.hi = span.lo;
+                        self.span = Some(span);
+                        self.found_use = true;
+                        return;
+                    }
+                },
+                // don't place use before extern crate
+                ItemKind::ExternCrate(_) => {}
+                // but place them before the first other item
+                _ => if self.span.map_or(true, |span| item.span < span ) {
+                    let mut span = item.span;
+                    span.hi = span.lo;
+                    self.span = Some(span);
+                },
+            }
+        }
+        assert!(self.span.is_some(), "a file can't have no items and emit suggestions");
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
     fn visit_item(&mut self, item: &'tcx Item) {
         self.resolve_item(item);
@@ -733,8 +779,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
     }
 }
 
-pub type ErrorMessage = Option<(Span, String)>;
-
 #[derive(Copy, Clone)]
 enum TypeParameters<'a, 'b> {
     NoTypeParameters,
@@ -793,7 +837,7 @@ impl<'a> Rib<'a> {
     fn new(kind: RibKind<'a>) -> Rib<'a> {
         Rib {
             bindings: FxHashMap(),
-            kind: kind,
+            kind,
         }
     }
 }
@@ -866,7 +910,7 @@ pub struct ModuleData<'a> {
     expansion: Mark,
 }
 
-pub type Module<'a> = &'a ModuleData<'a>;
+type Module<'a> = &'a ModuleData<'a>;
 
 impl<'a> ModuleData<'a> {
     fn new(parent: Option<Module<'a>>,
@@ -875,9 +919,9 @@ impl<'a> ModuleData<'a> {
            expansion: Mark,
            span: Span) -> Self {
         ModuleData {
-            parent: parent,
-            kind: kind,
-            normal_ancestor_id: normal_ancestor_id,
+            parent,
+            kind,
+            normal_ancestor_id,
             resolutions: RefCell::new(FxHashMap()),
             legacy_macro_resolutions: RefCell::new(Vec::new()),
             macro_resolutions: RefCell::new(Vec::new()),
@@ -887,8 +931,8 @@ impl<'a> ModuleData<'a> {
             globs: RefCell::new((Vec::new())),
             traits: RefCell::new(None),
             populated: Cell::new(normal_ancestor_id.is_local()),
-            span: span,
-            expansion: expansion,
+            span,
+            expansion,
         }
     }
 
@@ -990,6 +1034,16 @@ enum NameBindingKind<'a> {
 
 struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
 
+struct UseError<'a> {
+    err: DiagnosticBuilder<'a>,
+    /// Attach `use` statements for these candidates
+    candidates: Vec<ImportSuggestion>,
+    /// The node id of the module to place the use statements in
+    node_id: NodeId,
+    /// Whether the diagnostic should state that it's "better"
+    better: bool,
+}
+
 struct AmbiguityError<'a> {
     span: Span,
     name: Name,
@@ -1190,15 +1244,21 @@ pub struct Resolver<'a> {
     extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
 
     pub make_glob_map: bool,
-    // Maps imports to the names of items actually imported (this actually maps
-    // all imports, but only glob imports are actually interesting).
+    /// Maps imports to the names of items actually imported (this actually maps
+    /// all imports, but only glob imports are actually interesting).
     pub glob_map: GlobMap,
 
     used_imports: FxHashSet<(NodeId, Namespace)>,
     pub maybe_unused_trait_imports: NodeSet,
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
 
+    /// privacy errors are delayed until the end in order to deduplicate them
     privacy_errors: Vec<PrivacyError<'a>>,
+    /// ambiguity errors are delayed for deduplication
     ambiguity_errors: Vec<AmbiguityError<'a>>,
+    /// `use` injections are delayed for better placement and deduplication
+    use_injections: Vec<UseError<'a>>,
+
     gated_errors: FxHashSet<Span>,
     disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
 
@@ -1356,13 +1416,13 @@ impl<'a> Resolver<'a> {
         macro_defs.insert(Mark::root(), root_def_id);
 
         Resolver {
-            session: session,
+            session,
 
-            definitions: definitions,
+            definitions,
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
-            graph_root: graph_root,
+            graph_root,
             prelude: None,
 
             has_self: FxHashSet(),
@@ -1389,7 +1449,7 @@ impl<'a> Resolver<'a> {
             freevars_seen: NodeMap(),
             export_map: NodeMap(),
             trait_map: NodeMap(),
-            module_map: module_map,
+            module_map,
             block_map: NodeMap(),
             extern_module_map: FxHashMap(),
 
@@ -1398,13 +1458,15 @@ impl<'a> Resolver<'a> {
 
             used_imports: FxHashSet(),
             maybe_unused_trait_imports: NodeSet(),
+            maybe_unused_extern_crates: Vec::new(),
 
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
+            use_injections: Vec::new(),
             gated_errors: FxHashSet(),
             disallowed_shadowing: Vec::new(),
 
-            arenas: arenas,
+            arenas,
             dummy_binding: arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Def(Def::Err),
                 expansion: Mark::root(),
@@ -1416,14 +1478,14 @@ impl<'a> Resolver<'a> {
             use_extern_macros:
                 features.use_extern_macros || features.proc_macro || features.decl_macro,
 
-            crate_loader: crate_loader,
+            crate_loader,
             macro_names: FxHashSet(),
             global_macros: FxHashMap(),
             lexical_macro_resolutions: Vec::new(),
             macro_map: FxHashMap(),
             macro_exports: Vec::new(),
-            invocations: invocations,
-            macro_defs: macro_defs,
+            invocations,
+            macro_defs,
             local_macro_def_scopes: FxHashMap(),
             name_already_seen: FxHashMap(),
             whitelisted_legacy_custom_derives: Vec::new(),
@@ -1465,10 +1527,11 @@ impl<'a> Resolver<'a> {
         ImportResolver { resolver: self }.finalize_imports();
         self.current_module = self.graph_root;
         self.finalize_current_module_macro_resolutions();
+
         visit::walk_crate(self, krate);
 
         check_unused::check_crate(self, krate);
-        self.report_errors();
+        self.report_errors(krate);
         self.crate_loader.postprocess(krate);
     }
 
@@ -1502,7 +1565,7 @@ impl<'a> Resolver<'a> {
             NameBindingKind::Import { .. } => false,
             NameBindingKind::Ambiguity { b1, b2, legacy } => {
                 self.ambiguity_errors.push(AmbiguityError {
-                    span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy,
+                    span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy,
                 });
                 if legacy {
                     self.record_use(ident, ns, b1, span);
@@ -2413,25 +2476,20 @@ impl<'a> Resolver<'a> {
                 __diagnostic_used!(E0411);
                 err.code("E0411".into());
                 err.span_label(span, "`Self` is only available in traits and impls");
-                return err;
+                return (err, Vec::new());
             }
             if is_self_value(path, ns) {
                 __diagnostic_used!(E0424);
                 err.code("E0424".into());
                 err.span_label(span, format!("`self` value is only available in \
                                                methods with `self` parameter"));
-                return err;
+                return (err, Vec::new());
             }
 
             // Try to lookup the name in more relaxed fashion for better error reporting.
             let ident = *path.last().unwrap();
             let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected);
-            if !candidates.is_empty() {
-                let mut module_span = this.current_module.span;
-                module_span.hi = module_span.lo;
-                // Report import candidates as help and proceed searching for labels.
-                show_candidates(&mut err, module_span, &candidates, def.is_some());
-            } else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
+            if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
                 let enum_candidates =
                     this.lookup_import_candidates(ident.node.name, ns, is_enum_variant);
                 let mut enum_candidates = enum_candidates.iter()
@@ -2471,7 +2529,7 @@ impl<'a> Resolver<'a> {
                                                 format!("Self::{}", path_str));
                         }
                     }
-                    return err;
+                    return (err, candidates);
                 }
             }
 
@@ -2488,22 +2546,22 @@ impl<'a> Resolver<'a> {
                 match (def, source) {
                     (Def::Macro(..), _) => {
                         err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
-                        return err;
+                        return (err, candidates);
                     }
                     (Def::TyAlias(..), PathSource::Trait) => {
                         err.span_label(span, "type aliases cannot be used for traits");
-                        return err;
+                        return (err, candidates);
                     }
                     (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
                             err.span_label(parent.span, format!("did you mean `{}::{}`?",
                                                                  path_str, ident.node));
-                            return err;
+                            return (err, candidates);
                         }
                         ExprKind::MethodCall(ref segment, ..) => {
                             err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
                                                                  path_str, segment.identifier));
-                            return err;
+                            return (err, candidates);
                         }
                         _ => {}
                     },
@@ -2519,7 +2577,7 @@ impl<'a> Resolver<'a> {
                         }
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
                                                        path_str));
-                        return err;
+                        return (err, candidates);
                     }
                     _ => {}
                 }
@@ -2530,10 +2588,14 @@ impl<'a> Resolver<'a> {
                 err.span_label(base_span, fallback_label);
                 this.type_ascription_suggestion(&mut err, base_span);
             }
-            err
+            (err, candidates)
         };
         let report_errors = |this: &mut Self, def: Option<Def>| {
-            report_errors(this, def).emit();
+            let (err, candidates) = report_errors(this, def);
+            let def_id = this.current_module.normal_ancestor_id;
+            let node_id = this.definitions.as_local_node_id(def_id).unwrap();
+            let better = def.is_some();
+            this.use_injections.push(UseError { err, candidates, node_id, better });
             err_path_resolution()
         };
 
@@ -2915,7 +2977,7 @@ impl<'a> Resolver<'a> {
                             if record_used {
                                 vec.push(Freevar {
                                     def: prev_def,
-                                    span: span,
+                                    span,
                                 });
                                 seen.insert(node_id, depth);
                             }
@@ -2966,31 +3028,6 @@ impl<'a> Resolver<'a> {
         return def;
     }
 
-    // Calls `f` with a `Resolver` whose current lexical scope is `module`'s lexical scope,
-    // i.e. the module's items and the prelude (unless the module is `#[no_implicit_prelude]`).
-    // FIXME #34673: This needs testing.
-    pub fn with_module_lexical_scope<T, F>(&mut self, module: Module<'a>, f: F) -> T
-        where F: FnOnce(&mut Resolver<'a>) -> T,
-    {
-        self.with_empty_ribs(|this| {
-            this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
-            this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
-            f(this)
-        })
-    }
-
-    fn with_empty_ribs<T, F>(&mut self, f: F) -> T
-        where F: FnOnce(&mut Resolver<'a>) -> T,
-    {
-        let ribs = replace(&mut self.ribs, PerNS::<Vec<Rib>>::default());
-        let label_ribs = replace(&mut self.label_ribs, Vec::new());
-
-        let result = f(self);
-        self.ribs = ribs;
-        self.label_ribs = label_ribs;
-        result
-    }
-
     fn lookup_assoc_candidate<FilterFn>(&mut self,
                                         ident: Ident,
                                         ns: Namespace,
@@ -3458,8 +3495,9 @@ impl<'a> Resolver<'a> {
         vis.is_accessible_from(module.normal_ancestor_id, self)
     }
 
-    fn report_errors(&mut self) {
+    fn report_errors(&mut self, krate: &Crate) {
         self.report_shadowing_errors();
+        self.report_with_use_injections(krate);
         let mut reported_spans = FxHashSet();
 
         for &AmbiguityError { span, name, b1, b2, lexical, legacy } in &self.ambiguity_errors {
@@ -3507,6 +3545,22 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    fn report_with_use_injections(&mut self, krate: &Crate) {
+        for UseError { mut err, candidates, node_id, better } in self.use_injections.drain(..) {
+            let mut finder = UsePlacementFinder {
+                target_module: node_id,
+                span: None,
+                found_use: false,
+            };
+            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);
+            }
+            err.emit();
+        }
+    }
+
     fn report_shadowing_errors(&mut self) {
         for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
             self.resolve_legacy_scope(scope, ident, true);
@@ -3697,7 +3751,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
 fn show_candidates(err: &mut DiagnosticBuilder,
                    span: Span,
                    candidates: &[ImportSuggestion],
-                   better: bool) {
+                   better: bool,
+                   found_use: bool) {
 
     // we want consistent results across executions, but candidates are produced
     // by iterating through a hash map, so make sure they are ordered:
@@ -3713,7 +3768,14 @@ fn show_candidates(err: &mut DiagnosticBuilder,
     let msg = format!("possible {}candidate{} into scope", better, msg_diff);
 
     for candidate in &mut path_strings {
-        *candidate = format!("use {};\n", candidate);
+        // 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);
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 7572c4aa680..f8dc341653e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -273,7 +273,7 @@ impl<'a> base::Resolver for Resolver<'a> {
                         id: attr::mk_attr_id(),
                         style: ast::AttrStyle::Outer,
                         is_sugared_doc: false,
-                        span: span,
+                        span,
                     });
                 }
             }
@@ -491,7 +491,7 @@ impl<'a> Resolver<'a> {
                             let name = ident.name;
                             self.ambiguity_errors.push(AmbiguityError {
                                 span: path_span,
-                                name: name,
+                                name,
                                 b1: shadower,
                                 b2: binding,
                                 lexical: true,
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 26c398379dc..5616971e9d1 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -165,7 +165,7 @@ impl<'a> Resolver<'a> {
                        binding.def() != shadowed_glob.def() {
                         self.ambiguity_errors.push(AmbiguityError {
                             span: path_span,
-                            name: name,
+                            name,
                             lexical: false,
                             b1: binding,
                             b2: shadowed_glob,
@@ -265,13 +265,13 @@ impl<'a> Resolver<'a> {
         let current_module = self.current_module;
         let directive = self.arenas.alloc_import_directive(ImportDirective {
             parent: current_module,
-            module_path: module_path,
+            module_path,
             imported_module: Cell::new(None),
-            subclass: subclass,
-            span: span,
-            id: id,
+            subclass,
+            span,
+            id,
             vis: Cell::new(vis),
-            expansion: expansion,
+            expansion,
             used: Cell::new(false),
         });
 
@@ -311,13 +311,13 @@ impl<'a> Resolver<'a> {
 
         self.arenas.alloc_name_binding(NameBinding {
             kind: NameBindingKind::Import {
-                binding: binding,
-                directive: directive,
+                binding,
+                directive,
                 used: Cell::new(false),
                 legacy_self_import: false,
             },
             span: directive.span,
-            vis: vis,
+            vis,
             expansion: directive.expansion,
         })
     }
@@ -661,8 +661,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             legacy_self_import = Some(directive);
             let binding = this.arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Import {
-                    binding: binding,
-                    directive: directive,
+                    binding,
+                    directive,
                     used: Cell::new(false),
                     legacy_self_import: true,
                 },
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 658b6dbc4e3..619ebbc5422 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -83,8 +83,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
         DumpVisitor {
             tcx: save_ctxt.tcx,
-            save_ctxt: save_ctxt,
-            dumper: dumper,
+            save_ctxt,
+            dumper,
             span: span_utils.clone(),
             cur_scope: CRATE_NODE_ID,
             // mac_defs: HashSet::new(),
@@ -1351,7 +1351,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                                 self.span_from_span(sub_span.expect("No span found for var ref"));
                             self.dumper.dump_ref(Ref {
                                 kind: RefKind::Variable,
-                                span: span,
+                                span,
                                 ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did),
                             });
                         }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index c3d071d27d6..9b74df865d7 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_save_analysis"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -51,7 +48,7 @@ use std::env;
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
+use syntax::ast::{self, NodeId, PatKind, Attribute};
 use syntax::parse::lexer::comments::strip_doc_comment_decoration;
 use syntax::parse::token;
 use syntax::print::pprust;
@@ -80,8 +77,6 @@ pub struct SaveContext<'l, 'tcx: 'l> {
 
 #[derive(Debug)]
 pub enum Data {
-    /// Data about a macro use.
-    MacroUseData(MacroRef),
     RefData(Ref),
     DefData(Def),
     RelationData(Relation),
@@ -591,7 +586,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 self.tables.qpath_def(qpath, hir_id)
             }
 
-            Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
+            Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
                 HirDef::Local(def_id)
             }
 
@@ -759,11 +754,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         }
     }
 
-    #[inline]
-    pub fn enclosing_scope(&self, id: NodeId) -> NodeId {
-        self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID)
-    }
-
     fn docs_for_attrs(&self, attrs: &[Attribute]) -> String {
         let mut result = String::new();
 
@@ -881,7 +871,7 @@ pub struct DumpHandler<'a> {
 impl<'a> DumpHandler<'a> {
     pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
         DumpHandler {
-            odir: odir,
+            odir,
             cratename: cratename.to_owned()
         }
     }
@@ -976,9 +966,9 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
     info!("Dumping crate {}", cratename);
 
     let save_ctxt = SaveContext {
-        tcx: tcx,
+        tcx,
         tables: &ty::TypeckTables::empty(None),
-        analysis: analysis,
+        analysis,
         span_utils: SpanUtils::new(&tcx.sess),
         config: find_config(config),
     };
@@ -1048,7 +1038,7 @@ fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext) -> Vec<rls_data::A
         let value = value[2..value.len()-1].to_string();
 
         rls_data::Attribute {
-            value: value,
+            value,
             span: scx.span_from_span(attr.span),
         }
     }).collect()
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 6ef499694aa..c7e00245d63 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -149,7 +149,7 @@ fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
 
 fn text_sig(text: String) -> Signature {
     Signature {
-        text: text,
+        text,
         defs: vec![],
         refs: vec![],
     }
@@ -706,8 +706,8 @@ impl Sig for ast::Variant_ {
                 text.push('}');
                 Ok(Signature {
                     text,
-                    defs: defs,
-                    refs: refs,
+                    defs,
+                    refs,
                 })
             }
             ast::VariantData::Tuple(ref fields, id) => {
@@ -729,8 +729,8 @@ impl Sig for ast::Variant_ {
                 text.push(')');
                 Ok(Signature {
                     text,
-                    defs: defs,
-                    refs: refs,
+                    defs,
+                    refs,
                 })
             }
             ast::VariantData::Unit(id) => {
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 631907b28f8..36e4d09c963 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -32,7 +32,7 @@ pub struct SpanUtils<'a> {
 impl<'a> SpanUtils<'a> {
     pub fn new(sess: &'a Session) -> SpanUtils<'a> {
         SpanUtils {
-            sess: sess,
+            sess,
             err_count: Cell::new(0),
         }
     }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 144b484d7e8..5e50696b560 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -433,7 +433,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
     fn new(layout: TyLayout<'tcx>) -> ArgType<'tcx> {
         ArgType {
             kind: ArgKind::Direct,
-            layout: layout,
+            layout,
             cast: None,
             pad: None,
             attrs: ArgAttributes::default()
@@ -808,10 +808,10 @@ impl<'a, 'tcx> FnType<'tcx> {
         }
 
         FnType {
-            args: args,
-            ret: ret,
+            args,
+            ret,
             variadic: sig.variadic,
-            cconv: cconv
+            cconv,
         }
     }
 
diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index cbad43066e4..8863d4ea5ea 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -47,7 +47,7 @@ pub fn unwind(val: ValueRef, can_unwind: bool) {
     Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
 }
 
-/// Tell LLVM whether it should optimise function for size.
+/// Tell LLVM whether it should optimize function for size.
 #[inline]
 #[allow(dead_code)] // possibly useful function
 pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs
index 6ec40bd689c..0d39db9e10a 100644
--- a/src/librustc_trans/back/archive.rs
+++ b/src/librustc_trans/back/archive.rs
@@ -10,7 +10,7 @@
 
 //! A helper class for dealing with static archives
 
-use std::ffi::{CString, CStr, OsString};
+use std::ffi::{CString, CStr};
 use std::io;
 use std::mem;
 use std::path::{Path, PathBuf};
@@ -28,8 +28,6 @@ pub struct ArchiveConfig<'a> {
     pub dst: PathBuf,
     pub src: Option<PathBuf>,
     pub lib_search_paths: Vec<PathBuf>,
-    pub ar_prog: String,
-    pub command_path: OsString,
 }
 
 /// Helper for adding many files to an archive with a single invocation of
@@ -89,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> {
     /// by `config`.
     pub fn new(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
         ArchiveBuilder {
-            config: config,
+            config,
             removals: Vec::new(),
             additions: Vec::new(),
             should_update_symbols: false,
@@ -190,7 +188,7 @@ impl<'a> ArchiveBuilder<'a> {
             Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
         };
         self.additions.push(Addition::Archive {
-            archive: archive,
+            archive,
             skip: Box::new(skip),
         });
         Ok(())
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index a9bd8ea9010..4e211d83cff 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -138,12 +138,6 @@ pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>
     (Command::new("link.exe"), vec![])
 }
 
-pub fn get_ar_prog(sess: &Session) -> String {
-    sess.opts.cg.ar.clone().unwrap_or_else(|| {
-        sess.target.target.options.ar.clone()
-    })
-}
-
 fn command_path(sess: &Session) -> OsString {
     // The compiler's sysroot often has some bundled tools, so add it to the
     // PATH for the child.
@@ -379,12 +373,10 @@ fn archive_config<'a>(sess: &'a Session,
                       output: &Path,
                       input: Option<&Path>) -> ArchiveConfig<'a> {
     ArchiveConfig {
-        sess: sess,
+        sess,
         dst: output.to_path_buf(),
         src: input.map(|p| p.to_path_buf()),
         lib_search_paths: archive_search_paths(sess),
-        ar_prog: get_ar_prog(sess),
-        command_path: command_path(sess),
     }
 }
 
@@ -910,7 +902,7 @@ fn link_args(cmd: &mut Linker,
         let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
 
         if get_reloc_model(sess) == llvm::RelocMode::PIC
-            && !args.any(|x| *x == "-static") {
+            && !sess.crt_static() && !args.any(|x| *x == "-static") {
             cmd.position_independent_executable();
         }
     }
@@ -974,11 +966,13 @@ fn link_args(cmd: &mut Linker,
     add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
     add_upstream_native_libraries(cmd, sess, crate_type);
 
-    // # Telling the linker what we're doing
-
+    // Tell the linker what we're doing.
     if crate_type != config::CrateTypeExecutable {
         cmd.build_dylib(out_filename);
     }
+    if crate_type == config::CrateTypeExecutable && sess.crt_static() {
+        cmd.build_static_executable();
+    }
 
     // FIXME (#2397): At some point we want to rpath our guesses as to
     // where extern libraries might live, based on the
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index b364f92f104..9b0a5e3f4a5 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -49,22 +49,22 @@ impl<'a, 'tcx> LinkerInfo {
         match sess.linker_flavor() {
             LinkerFlavor::Msvc => {
                 Box::new(MsvcLinker {
-                    cmd: cmd,
-                    sess: sess,
+                    cmd,
+                    sess,
                     info: self
                 }) as Box<Linker>
             }
             LinkerFlavor::Em =>  {
                 Box::new(EmLinker {
-                    cmd: cmd,
-                    sess: sess,
+                    cmd,
+                    sess,
                     info: self
                 }) as Box<Linker>
             }
             LinkerFlavor::Gcc =>  {
                 Box::new(GccLinker {
-                    cmd: cmd,
-                    sess: sess,
+                    cmd,
+                    sess,
                     info: self,
                     hinted_static: false,
                     is_ld: false,
@@ -72,8 +72,8 @@ impl<'a, 'tcx> LinkerInfo {
             }
             LinkerFlavor::Ld => {
                 Box::new(GccLinker {
-                    cmd: cmd,
-                    sess: sess,
+                    cmd,
+                    sess,
                     info: self,
                     hinted_static: false,
                     is_ld: true,
@@ -110,6 +110,7 @@ pub trait Linker {
     fn debuginfo(&mut self);
     fn no_default_libraries(&mut self);
     fn build_dylib(&mut self, out_filename: &Path);
+    fn build_static_executable(&mut self);
     fn args(&mut self, args: &[String]);
     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
     fn subsystem(&mut self, subsystem: &str);
@@ -179,6 +180,7 @@ impl<'a> Linker for GccLinker<'a> {
     fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
     fn partial_relro(&mut self) { self.linker_arg("-z,relro"); }
     fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); }
+    fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
 
     fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
@@ -396,6 +398,10 @@ impl<'a> Linker for MsvcLinker<'a> {
         self.cmd.arg(arg);
     }
 
+    fn build_static_executable(&mut self) {
+        // noop
+    }
+
     fn gc_sections(&mut self, _keep_metadata: bool) {
         // MSVC's ICF (Identical COMDAT Folding) link optimization is
         // slow for Rust and thus we disable it by default when not in
@@ -683,6 +689,10 @@ impl<'a> Linker for EmLinker<'a> {
         bug!("building dynamic library is unsupported on Emscripten")
     }
 
+    fn build_static_executable(&mut self) {
+        // noop
+    }
+
     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
         let symbols = &self.info.exports[&crate_type];
 
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 94cae37761f..3f9b28d3d61 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -237,7 +237,7 @@ impl ModuleConfig {
     fn new(sess: &Session, passes: Vec<String>) -> ModuleConfig {
         ModuleConfig {
             tm: create_target_machine(sess),
-            passes: passes,
+            passes,
             opt_level: None,
             opt_size: None,
 
@@ -426,8 +426,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
     let tm = config.tm;
 
     let fv = HandlerFreeVars {
-        cgcx: cgcx,
-        diag_handler: diag_handler,
+        cgcx,
+        diag_handler,
     };
     let fv = &fv as *const HandlerFreeVars as *mut c_void;
 
@@ -785,8 +785,6 @@ pub fn start_async_translation(sess: &Session,
         crate_name,
         link,
         metadata,
-        exported_symbols,
-        no_builtins,
         windows_subsystem,
         linker_info,
         no_integrated_as,
@@ -1012,9 +1010,9 @@ fn build_work_item(mtrans: ModuleTranslation,
                    -> WorkItem
 {
     WorkItem {
-        mtrans: mtrans,
-        config: config,
-        output_names: output_names
+        mtrans,
+        config,
+        output_names,
     }
 }
 
@@ -1136,17 +1134,17 @@ fn start_executing_work(sess: &Session,
 
     let cgcx = CodegenContext {
         crate_types: sess.crate_types.borrow().clone(),
-        each_linked_rlib_for_lto: each_linked_rlib_for_lto,
+        each_linked_rlib_for_lto,
         lto: sess.lto(),
         no_landing_pads: sess.no_landing_pads(),
         opts: Arc::new(sess.opts.clone()),
         time_passes: sess.time_passes(),
-        exported_symbols: exported_symbols,
+        exported_symbols,
         plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
         remark: sess.opts.cg.remark.clone(),
         worker: 0,
         incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
-        coordinator_send: coordinator_send,
+        coordinator_send,
         diag_emitter: shared_emitter.clone(),
         time_graph,
     };
@@ -1801,8 +1799,6 @@ pub struct OngoingCrateTranslation {
     crate_name: Symbol,
     link: LinkMeta,
     metadata: EncodedMetadata,
-    exported_symbols: Arc<ExportedSymbols>,
-    no_builtins: bool,
     windows_subsystem: Option<String>,
     linker_info: LinkerInfo,
     no_integrated_as: bool,
@@ -1852,13 +1848,10 @@ impl OngoingCrateTranslation {
             crate_name: self.crate_name,
             link: self.link,
             metadata: self.metadata,
-            exported_symbols: self.exported_symbols,
-            no_builtins: self.no_builtins,
             windows_subsystem: self.windows_subsystem,
             linker_info: self.linker_info,
 
             modules: compiled_modules.modules,
-            metadata_module: compiled_modules.metadata_module,
             allocator_module: compiled_modules.allocator_module,
         };
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index b4a2891f94c..e4b090471d7 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -99,9 +99,9 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> {
     pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> {
         let istart = ccx.stats().n_llvm_insns.get();
         StatRecorder {
-            ccx: ccx,
+            ccx,
             name: Some(name),
-            istart: istart,
+            istart,
         }
     }
 }
@@ -664,7 +664,7 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt) {
     }
 }
 
-/// Create the `main` function which will initialise the rust runtime and call
+/// Create the `main` function which will initialize the rust runtime and call
 /// users main function.
 fn maybe_create_entry_wrapper(ccx: &CrateContext) {
     let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
@@ -1058,8 +1058,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let (llcx, llmod) =
                 context::create_context_and_module(tcx.sess, "allocator");
             let modules = ModuleLlvm {
-                llmod: llmod,
-                llcx: llcx,
+                llmod,
+                llcx,
             };
             time(tcx.sess.time_passes(), "write allocator module", || {
                 allocator::trans(tcx, &modules, kind)
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 5103ca5c5e1..8a585e72f59 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -70,8 +70,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             llvm::LLVMCreateBuilderInContext(ccx.llcx())
         };
         Builder {
-            llbuilder: llbuilder,
-            ccx: ccx,
+            llbuilder,
+            ccx,
         }
     }
 
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index b31295f4022..c5de3a4ffb0 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -331,8 +331,8 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 
     {
         let mut visitor = RootCollector {
-            scx: scx,
-            mode: mode,
+            scx,
+            mode,
             exported_symbols,
             output: &mut roots,
         };
@@ -699,7 +699,8 @@ fn visit_instance_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         }
         ty::InstanceDef::ClosureOnceShim { .. } |
         ty::InstanceDef::Item(..) |
-        ty::InstanceDef::FnPtrShim(..) => {
+        ty::InstanceDef::FnPtrShim(..) |
+        ty::InstanceDef::CloneShim(..) => {
             output.push(create_fn_trans_item(instance));
         }
     }
@@ -716,7 +717,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
         ty::InstanceDef::Virtual(..) |
         ty::InstanceDef::FnPtrShim(..) |
         ty::InstanceDef::DropGlue(..) |
-        ty::InstanceDef::Intrinsic(_) => return true
+        ty::InstanceDef::Intrinsic(_) |
+        ty::InstanceDef::CloneShim(..) => return true
     };
     match tcx.hir.get_if_local(def_id) {
         Some(hir_map::NodeForeignItem(..)) => {
@@ -1035,9 +1037,9 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     let mir = scx.tcx().instance_mir(instance.def);
 
     let mut visitor = MirNeighborCollector {
-        scx: scx,
+        scx,
         mir: &mir,
-        output: output,
+        output,
         param_substs: instance.substs,
         const_context,
     };
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 0cc499577bb..09aa3d2335a 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -177,7 +177,7 @@ pub struct Funclet {
 impl Funclet {
     pub fn new(cleanuppad: ValueRef) -> Funclet {
         Funclet {
-            cleanuppad: cleanuppad,
+            cleanuppad,
             operand: OperandBundleDef::new("funclet", &[cleanuppad]),
         }
     }
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index bec39e3cde6..f2b07cf6a58 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -27,10 +27,9 @@ use type_::Type;
 use rustc_data_structures::base_n;
 use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
 use rustc::session::Session;
-use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
-use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
@@ -39,7 +38,6 @@ use std::iter;
 use std::str;
 use std::sync::Arc;
 use std::marker::PhantomData;
-use syntax::ast;
 use syntax::symbol::InternedString;
 use syntax_pos::DUMMY_SP;
 use abi::Abi;
@@ -124,12 +122,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
     /// Cache of emitted const globals (value -> global)
     const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>,
 
-    /// Cache of emitted const values
-    const_values: RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>), ValueRef>>,
-
-    /// Cache of external const values
-    extern_const_values: RefCell<DefIdMap<ValueRef>>,
-
     /// Mapping from static definitions to their DefId's.
     statics: RefCell<FxHashMap<ValueRef, DefId>>,
 
@@ -144,7 +136,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
     used_statics: RefCell<Vec<ValueRef>>,
 
     lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>,
-    type_hashcodes: RefCell<FxHashMap<Ty<'tcx>, String>>,
     int_type: Type,
     opaque_vec_type: Type,
     str_slice_type: Type,
@@ -157,9 +148,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
 
     intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>,
 
-    /// Depth of the current type-of computation - used to bail out
-    type_of_depth: Cell<usize>,
-
     /// A counter that is used for generating local symbol names
     local_gen_sym_counter: Cell<usize>,
 
@@ -323,10 +311,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
         let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc;
 
         SharedCrateContext {
-            tcx: tcx,
-            check_overflow: check_overflow,
-            use_dll_storage_attrs: use_dll_storage_attrs,
-            output_filenames: output_filenames,
+            tcx,
+            check_overflow,
+            use_dll_storage_attrs,
+            output_filenames,
         }
     }
 
@@ -395,10 +383,10 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
             };
 
             let local_ccx = LocalCrateContext {
-                llmod: llmod,
-                llcx: llcx,
+                llmod,
+                llcx,
                 stats: Stats::default(),
-                codegen_unit: codegen_unit,
+                codegen_unit,
                 crate_trans_items,
                 exported_symbols,
                 instances: RefCell::new(FxHashMap()),
@@ -406,22 +394,18 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
                 const_cstr_cache: RefCell::new(FxHashMap()),
                 const_unsized: RefCell::new(FxHashMap()),
                 const_globals: RefCell::new(FxHashMap()),
-                const_values: RefCell::new(FxHashMap()),
-                extern_const_values: RefCell::new(DefIdMap()),
                 statics: RefCell::new(FxHashMap()),
                 statics_to_rauw: RefCell::new(Vec::new()),
                 used_statics: RefCell::new(Vec::new()),
                 lltypes: RefCell::new(FxHashMap()),
-                type_hashcodes: RefCell::new(FxHashMap()),
                 int_type: Type::from_ref(ptr::null_mut()),
                 opaque_vec_type: Type::from_ref(ptr::null_mut()),
                 str_slice_type: Type::from_ref(ptr::null_mut()),
-                dbg_cx: dbg_cx,
+                dbg_cx,
                 eh_personality: Cell::new(None),
                 eh_unwind_resume: Cell::new(None),
                 rust_try_fn: Cell::new(None),
                 intrinsics: RefCell::new(FxHashMap()),
-                type_of_depth: Cell::new(0),
                 local_gen_sym_counter: Cell::new(0),
                 placeholder: PhantomData,
             };
@@ -462,7 +446,7 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
                  -> CrateContext<'a, 'tcx> {
         assert!(local_ccxs.len() == 1);
         CrateContext {
-            shared: shared,
+            shared,
             local_ccx: &local_ccxs[0]
         }
     }
@@ -545,15 +529,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.local().const_globals
     }
 
-    pub fn const_values<'a>(&'a self) -> &'a RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>),
-                                                               ValueRef>> {
-        &self.local().const_values
-    }
-
-    pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
-        &self.local().extern_const_values
-    }
-
     pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> {
         &self.local().statics
     }
@@ -570,10 +545,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.local().lltypes
     }
 
-    pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, String>> {
-        &self.local().type_hashcodes
-    }
-
     pub fn stats<'a>(&'a self) -> &'a Stats {
         &self.local().stats
     }
@@ -582,10 +553,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         self.local().int_type
     }
 
-    pub fn opaque_vec_type(&self) -> Type {
-        self.local().opaque_vec_type
-    }
-
     pub fn str_slice_type(&self) -> Type {
         self.local().str_slice_type
     }
@@ -602,27 +569,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.local().intrinsics
     }
 
-    pub fn obj_size_bound(&self) -> u64 {
-        self.tcx().data_layout.obj_size_bound()
-    }
-
-    pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! {
-        self.sess().fatal(
-            &format!("the type `{:?}` is too big for the current architecture",
-                    obj))
-    }
-
-    pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> {
-        let current_depth = self.local().type_of_depth.get();
-        debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth);
-        if current_depth > self.sess().recursion_limit.get() {
-            self.sess().fatal(
-                &format!("overflow representing the type `{}`", ty))
-        }
-        self.local().type_of_depth.set(current_depth + 1);
-        TypeOfDepthLock(self.local())
-    }
-
     pub fn check_overflow(&self) -> bool {
         self.shared.check_overflow
     }
@@ -631,12 +577,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         self.shared.use_dll_storage_attrs()
     }
 
-    /// Given the def-id of some item that has no type parameters, make
-    /// a suitable "empty substs" for it.
-    pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
-        self.tcx().empty_substs_for_def_id(item_def_id)
-    }
-
     /// Generate a new symbol name with the given prefix. This symbol name must
     /// only be used for definitions with `internal` or `private` linkage.
     pub fn generate_local_symbol_name(&self, prefix: &str) -> String {
@@ -776,14 +716,6 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
     }
 }
 
-pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>);
-
-impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> {
-    fn drop(&mut self) {
-        self.0.type_of_depth.set(self.0.type_of_depth.get() - 1);
-    }
-}
-
 /// Declare any llvm intrinsics that you might need
 fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
     macro_rules! ifn {
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index ae618c7e170..95f13ea8716 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -129,7 +129,7 @@ fn make_mir_scope(ccx: &CrateContext,
             loc.col.to_usize() as c_uint)
     };
     scopes[scope] = MirDebugScope {
-        scope_metadata: scope_metadata,
+        scope_metadata,
         file_start_pos: loc.file.start_pos,
         file_end_pos: loc.file.end_pos,
     };
diff --git a/src/librustc_trans/debuginfo/doc.rs b/src/librustc_trans/debuginfo/doc.rs
index 7a739071506..93dca03e1ff 100644
--- a/src/librustc_trans/debuginfo/doc.rs
+++ b/src/librustc_trans/debuginfo/doc.rs
@@ -92,7 +92,7 @@
 //! encounters a recursive reference, it will hit the cache and does not try to
 //! describe the type anew.
 //!
-//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum,
+//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum,
 //! which represents a kind of continuation, storing all state needed to
 //! continue traversal at the type members after the type has been registered
 //! with the cache. (This implementation approach might be a tad over-
@@ -156,13 +156,13 @@
 //! (2) Structs, enums and traits have a multipart identifier
 //!
 //!     (1) The first part is the SVH (strict version hash) of the crate they
-//!          wereoriginally defined in
+//!          were originally defined in
 //!
 //!     (2) The second part is the ast::NodeId of the definition in their
-//!          originalcrate
+//!          original crate
 //!
 //!     (3) The final part is a concatenation of the type IDs of their concrete
-//!          typearguments if they are generic types.
+//!          type arguments if they are generic types.
 //!
 //! (3) Tuple-, pointer and function types are structurally identified, which
 //!     means that they are equivalent if their component types are equivalent
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 61204b88e13..9aba075a20c 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -205,11 +205,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
     type_map.register_type_with_metadata(unfinished_type, metadata_stub);
 
     UnfinishedMetadata {
-        unfinished_type: unfinished_type,
-        unique_type_id: unique_type_id,
-        metadata_stub: metadata_stub,
-        llvm_type: llvm_type,
-        member_description_factory: member_description_factory,
+        unfinished_type,
+        unique_type_id,
+        metadata_stub,
+        llvm_type,
+        member_description_factory,
     }
 }
 
@@ -847,8 +847,8 @@ struct MetadataCreationResult {
 impl MetadataCreationResult {
     fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
         MetadataCreationResult {
-            metadata: metadata,
-            already_stored_in_typemap: already_stored_in_typemap
+            metadata,
+            already_stored_in_typemap,
         }
     }
 }
@@ -947,10 +947,10 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
             let offset = FixedMemberOffset { bytes: offsets[i].bytes() as usize};
 
             MemberDescription {
-                name: name,
+                name,
                 llvm_type: type_of::in_memory_type_of(cx, fty),
                 type_metadata: type_metadata(cx, fty, self.span),
-                offset: offset,
+                offset,
                 flags: DIFlags::FlagZero,
             }
         }).collect()
@@ -987,9 +987,9 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         struct_llvm_type,
         StructMDF(StructMemberDescriptionFactory {
             ty: struct_type,
-            variant: variant,
-            substs: substs,
-            span: span,
+            variant,
+            substs,
+            span,
         })
     )
 }
@@ -1052,7 +1052,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         TupleMDF(TupleMemberDescriptionFactory {
             ty: tuple_type,
             component_types: component_types.to_vec(),
-            span: span,
+            span,
         })
     )
 }
@@ -1111,9 +1111,9 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         union_metadata_stub,
         union_llvm_type,
         UnionMDF(UnionMemberDescriptionFactory {
-            variant: variant,
-            substs: substs,
-            span: span,
+            variant,
+            substs,
+            span,
         })
     )
 }
@@ -1462,14 +1462,14 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let member_description_factory =
         VariantMDF(VariantMemberDescriptionFactory {
             offsets: &struct_def.offsets[..],
-            args: args,
+            args,
             discriminant_type_metadata: match discriminant_info {
                 RegularDiscriminant(discriminant_type_metadata) => {
                     Some(discriminant_type_metadata)
                 }
                 _ => None
             },
-            span: span,
+            span,
         });
 
     (metadata_stub, variant_llvm_type, member_description_factory)
@@ -1590,12 +1590,12 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         enum_metadata,
         enum_llvm_type,
         EnumMDF(EnumMemberDescriptionFactory {
-            enum_type: enum_type,
+            enum_type,
             type_rep: type_rep.layout,
-            discriminant_type_metadata: discriminant_type_metadata,
-            containing_scope: containing_scope,
-            file_metadata: file_metadata,
-            span: span,
+            discriminant_type_metadata,
+            containing_scope,
+            file_metadata,
+            span,
         }),
     );
 
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 68432c22f81..83366c13453 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -87,9 +87,9 @@ impl<'tcx> CrateDebugContext<'tcx> {
         // DIBuilder inherits context from the module, so we'd better use the same one
         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
         CrateDebugContext {
-            llcontext: llcontext,
-            llmod: llmod,
-            builder: builder,
+            llcontext,
+            llmod,
+            builder,
             created_files: RefCell::new(FxHashMap()),
             created_enum_disr_types: RefCell::new(FxHashMap()),
             type_map: RefCell::new(TypeMap::new()),
@@ -292,7 +292,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     // Initialize fn debug context (including scope map and namespace map)
     let fn_debug_context = FunctionDebugContextData {
-        fn_metadata: fn_metadata,
+        fn_metadata,
         source_locations_enabled: Cell::new(false),
         defining_crate: def_id.krate,
     };
diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs
index e99e26261a3..7393802294a 100644
--- a/src/librustc_trans/debuginfo/source_loc.rs
+++ b/src/librustc_trans/debuginfo/source_loc.rs
@@ -72,9 +72,9 @@ pub enum InternalDebugLocation {
 impl InternalDebugLocation {
     pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
         KnownLocation {
-            scope: scope,
-            line: line,
-            col: col,
+            scope,
+            line,
+            col,
         }
     }
 }
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 5a4a5b95cf9..1758e331129 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_trans"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -36,7 +33,6 @@
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
-use std::sync::Arc;
 
 extern crate flate2;
 extern crate libc;
@@ -46,7 +42,7 @@ extern crate rustc_allocator;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate rustc_incremental;
-pub extern crate rustc_llvm as llvm;
+extern crate rustc_llvm as llvm;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_const_math;
 #[macro_use]
@@ -78,7 +74,7 @@ pub mod back {
     pub(crate) mod symbol_export;
     pub(crate) mod symbol_names;
     pub mod write;
-    pub mod rpath;
+    mod rpath;
 }
 
 mod diagnostics;
@@ -138,8 +134,8 @@ pub struct ModuleTranslation {
     /// unique amongst **all** crates.  Therefore, it should contain
     /// something unique to this crate (e.g., a module path) as well
     /// as the crate name and disambiguator.
-    pub name: String,
-    pub symbol_name_hash: u64,
+    name: String,
+    symbol_name_hash: u64,
     pub source: ModuleSource,
     pub kind: ModuleKind,
 }
@@ -206,7 +202,7 @@ pub enum ModuleSource {
 
 #[derive(Copy, Clone, Debug)]
 pub struct ModuleLlvm {
-    pub llcx: llvm::ContextRef,
+    llcx: llvm::ContextRef,
     pub llmod: llvm::ModuleRef,
 }
 
@@ -216,14 +212,11 @@ unsafe impl Sync for ModuleTranslation { }
 pub struct CrateTranslation {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
-    pub metadata_module: CompiledModule,
-    pub allocator_module: Option<CompiledModule>,
+    allocator_module: Option<CompiledModule>,
     pub link: rustc::middle::cstore::LinkMeta,
     pub metadata: rustc::middle::cstore::EncodedMetadata,
-    pub exported_symbols: Arc<back::symbol_export::ExportedSymbols>,
-    pub no_builtins: bool,
-    pub windows_subsystem: Option<String>,
-    pub linker_info: back::linker::LinkerInfo
+    windows_subsystem: Option<String>,
+    linker_info: back::linker::LinkerInfo
 }
 
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 9bb29c340d9..28fe1044e74 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -673,8 +673,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         Ref(ptr, align)
                     };
                     let op = OperandRef {
-                        val: val,
-                        ty: ty
+                        val,
+                        ty,
                     };
                     self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
@@ -697,7 +697,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     // If the tuple is immediate, the elements are as well
                     let op = OperandRef {
                         val: Immediate(elem),
-                        ty: ty
+                        ty,
                     };
                     self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
@@ -713,7 +713,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     // Pair is always made up of immediates
                     let op = OperandRef {
                         val: Immediate(elem),
-                        ty: ty
+                        ty,
                     };
                     self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def);
                 }
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 53469689bc7..293e6462de2 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -57,8 +57,8 @@ pub struct Const<'tcx> {
 impl<'tcx> Const<'tcx> {
     pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
         Const {
-            llval: llval,
-            ty: ty
+            llval,
+            ty,
         }
     }
 
@@ -158,7 +158,7 @@ impl<'tcx> Const<'tcx> {
         };
 
         OperandRef {
-            val: val,
+            val,
             ty: self.ty
         }
     }
@@ -247,9 +247,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
            args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>)
            -> MirConstContext<'a, 'tcx> {
         let mut context = MirConstContext {
-            ccx: ccx,
-            mir: mir,
-            substs: substs,
+            ccx,
+            mir,
+            substs,
             locals: (0..mir.local_decls.len()).map(|_| None).collect(),
         };
         for (i, arg) in args.into_iter().enumerate() {
@@ -491,7 +491,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                 };
                 ConstLvalue {
                     base: projected,
-                    llextra: llextra,
+                    llextra,
                     ty: projected_ty
                 }
             }
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index af8976967a1..89c76ccdd27 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -380,7 +380,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 };
                 LvalueRef {
                     llval: llprojected,
-                    llextra: llextra,
+                    llextra,
                     ty: projected_ty,
                     alignment: align,
                 }
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index d0f7f27d5a8..a67fa070324 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -228,19 +228,19 @@ pub fn trans_mir<'a, 'tcx: 'a>(
     let (landing_pads, funclets) = create_funclets(&bcx, &cleanup_kinds, &block_bcxs);
 
     let mut mircx = MirContext {
-        mir: mir,
-        llfn: llfn,
-        fn_ty: fn_ty,
-        ccx: ccx,
+        mir,
+        llfn,
+        fn_ty,
+        ccx,
         llpersonalityslot: None,
         blocks: block_bcxs,
         unreachable_block: None,
-        cleanup_kinds: cleanup_kinds,
-        landing_pads: landing_pads,
+        cleanup_kinds,
+        landing_pads,
         funclets: &funclets,
-        scopes: scopes,
+        scopes,
         locals: IndexVec::new(),
-        debug_context: debug_context,
+        debug_context,
         param_substs: {
             assert!(!instance.substs.needs_infer());
             instance.substs
@@ -486,7 +486,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
                 OperandValue::Immediate(llarg)
             };
             let operand = OperandRef {
-                val: val,
+                val,
                 ty: arg_ty
             };
             return LocalRef::Operand(Some(operand.unpack_if_pair(bcx)));
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 1b8a05b6f6c..9ce1749190b 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -98,8 +98,8 @@ impl<'a, 'tcx> OperandRef<'tcx> {
             OperandValue::Immediate(C_null(llty))
         };
         OperandRef {
-            val: val,
-            ty: ty
+            val,
+            ty,
         }
     }
 
@@ -122,7 +122,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
         };
         LvalueRef {
             llval: llptr,
-            llextra: llextra,
+            llextra,
             ty: LvalueTy::from_ty(projected_ty),
             alignment: Alignment::AbiAligned,
         }
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index a23e1a0684b..096f43e44ab 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -29,7 +29,7 @@ use type_of;
 use tvec;
 use value::Value;
 
-use super::MirContext;
+use super::{MirContext, LocalRef};
 use super::constant::const_scalar_checked_binop;
 use super::operand::{OperandRef, OperandValue};
 use super::lvalue::LvalueRef;
@@ -148,9 +148,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                     dest.llval, dest.ty, dest.alignment);
                                 let field_index = active_field_index.unwrap_or(i);
                                 val.ty = LvalueTy::Downcast {
-                                    adt_def: adt_def,
+                                    adt_def,
                                     substs: self.monomorphize(&substs),
-                                    variant_index: variant_index,
+                                    variant_index,
                                 };
                                 let (lldest_i, align) = val.trans_field_ptr(&bcx, field_index);
                                 self.store_operand(&bcx, lldest_i, align.to_align(), op);
@@ -348,7 +348,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                     }
                 };
                 let operand = OperandRef {
-                    val: val,
+                    val,
                     ty: cast_ty
                 };
                 (bcx, operand)
@@ -381,9 +381,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
             }
 
             mir::Rvalue::Len(ref lvalue) => {
-                let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
+                let size = self.evaluate_array_len(&bcx, lvalue);
                 let operand = OperandRef {
-                    val: OperandValue::Immediate(tr_lvalue.len(bcx.ccx)),
+                    val: OperandValue::Immediate(size),
                     ty: bcx.tcx().types.usize,
                 };
                 (bcx, operand)
@@ -512,6 +512,26 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
         }
     }
 
+    fn evaluate_array_len(&mut self,
+                          bcx: &Builder<'a, 'tcx>,
+                          lvalue: &mir::Lvalue<'tcx>) -> ValueRef
+    {
+        // ZST are passed as operands and require special handling
+        // because trans_lvalue() panics if Local is operand.
+        if let mir::Lvalue::Local(index) = *lvalue {
+            if let LocalRef::Operand(Some(op)) = self.locals[index] {
+                if common::type_is_zero_size(bcx.ccx, op.ty) {
+                    if let ty::TyArray(_, n) = op.ty.sty {
+                        return common::C_uint(bcx.ccx, n);
+                    }
+                }
+            }
+        }
+        // use common size calculation for non zero-sized types
+        let tr_value = self.trans_lvalue(&bcx, lvalue);
+        return tr_value.len(bcx.ccx);
+    }
+
     pub fn trans_scalar_binop(&mut self,
                               bcx: &Builder<'a, 'tcx>,
                               op: mir::BinOp,
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 1f6a262162d..b0d8be23b0d 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -143,6 +143,12 @@ fn resolve_associated_item<'a, 'tcx>(
                 substs: rcvr_substs
             }
         }
+        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items.clone_trait() => {
+            Instance {
+                def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
+                substs: rcvr_substs
+            }
+        }
         _ => {
             bug!("static call to invalid vtable: {:?}", vtbl)
         }
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 63c7b18e8d2..26256fa78dd 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -361,7 +361,8 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
                                 InstanceDef::Virtual(..) |
                                 InstanceDef::Intrinsic(..) |
                                 InstanceDef::ClosureOnceShim { .. } |
-                                InstanceDef::DropGlue(..) => {
+                                InstanceDef::DropGlue(..) |
+                                InstanceDef::CloneShim(..) => {
                                     bug!("partitioning: Encountered unexpected
                                           root translation item: {:?}",
                                           trans_item)
@@ -603,7 +604,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't
                 ty::InstanceDef::ClosureOnceShim { .. } |
                 ty::InstanceDef::Intrinsic(..) |
                 ty::InstanceDef::DropGlue(..) |
-                ty::InstanceDef::Virtual(..) => return None
+                ty::InstanceDef::Virtual(..) |
+                ty::InstanceDef::CloneShim(..) => return None
             };
 
             // If this is a method, we want to put it into the same module as
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index b94fd13c3a4..38232ed1d11 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -384,9 +384,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                omit_local_crate_name: bool)
                -> Self {
         DefPathBasedNames {
-            tcx: tcx,
-            omit_disambiguators: omit_disambiguators,
-            omit_local_crate_name: omit_local_crate_name,
+            tcx,
+            omit_disambiguators,
+            omit_local_crate_name,
         }
     }
 
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index d70afc0cce5..b8a8068d36a 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -237,19 +237,6 @@ impl Type {
         ty!(llvm::LLVMPointerType(self.to_ref(), 0))
     }
 
-    pub fn is_aggregate(&self) -> bool {
-        match self.kind() {
-            TypeKind::Struct | TypeKind::Array => true,
-            _ =>  false
-        }
-    }
-
-    pub fn is_packed(&self) -> bool {
-        unsafe {
-            llvm::LLVMIsPackedStruct(self.to_ref()) == True
-        }
-    }
-
     pub fn element_type(&self) -> Type {
         unsafe {
             Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
@@ -263,12 +250,6 @@ impl Type {
         }
     }
 
-    pub fn array_length(&self) -> usize {
-        unsafe {
-            llvm::LLVMGetArrayLength(self.to_ref()) as usize
-        }
-    }
-
     pub fn field_types(&self) -> Vec<Type> {
         unsafe {
             let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as usize;
@@ -282,10 +263,6 @@ impl Type {
         }
     }
 
-    pub fn return_type(&self) -> Type {
-        ty!(llvm::LLVMGetReturnType(self.to_ref()))
-    }
-
     pub fn func_params(&self) -> Vec<Type> {
         unsafe {
             let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize;
@@ -324,13 +301,4 @@ impl Type {
             I128 => Type::i128(cx),
         }
     }
-
-    pub fn from_primitive(ccx: &CrateContext, p: layout::Primitive) -> Type {
-        match p {
-            layout::Int(i) => Type::from_integer(ccx, i),
-            layout::F32 => Type::f32(ccx),
-            layout::F64 => Type::f64(ccx),
-            layout::Pointer => bug!("It is not possible to convert Pointer directly to Type.")
-        }
-    }
 }
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 81e83076f8c..90e17906328 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -12,9 +12,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_trans_utils"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs
index 264158f0de9..aa8637fabe8 100644
--- a/src/librustc_trans_utils/link.rs
+++ b/src/librustc_trans_utils/link.rs
@@ -123,8 +123,11 @@ pub fn invalid_output_for_target(sess: &Session,
     match (sess.target.target.options.dynamic_linking,
            sess.target.target.options.executables, crate_type) {
         (false, _, config::CrateTypeCdylib) |
-        (false, _, config::CrateTypeProcMacro) |
-        (false, _, config::CrateTypeDylib) => true,
+        (false, _, config::CrateTypeDylib) |
+        (false, _, config::CrateTypeProcMacro) => true,
+        (true, _, config::CrateTypeCdylib) |
+        (true, _, config::CrateTypeDylib) => sess.crt_static() &&
+            !sess.target.target.options.crt_static_allows_dylibs,
         (_, false, config::CrateTypeExecutable) => true,
         _ => false
     }
diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml
index 97c1181e3a2..7b83985ba67 100644
--- a/src/librustc_tsan/Cargo.toml
+++ b/src/librustc_tsan/Cargo.toml
@@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" }
 cmake = "0.1.18"
 
 [dependencies]
+alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs
index 54941362e84..3429e3bda0f 100644
--- a/src/librustc_tsan/lib.rs
+++ b/src/librustc_tsan/lib.rs
@@ -9,8 +9,10 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(sanitizer_runtime)]
 #![feature(alloc_system)]
+#![feature(allocator_api)]
+#![feature(global_allocator)]
+#![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
@@ -18,3 +20,8 @@
             issue = "0")]
 
 extern crate alloc_system;
+
+use alloc_system::System;
+
+#[global_allocator]
+static ALLOC: System = System;
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 2910d25486e..ee1e6bd950f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -22,16 +22,14 @@ use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
-use rustc::lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_back::slice;
 use require_c_abi_if_variadic;
-use util::common::{ErrorReported, FN_OUTPUT_NAME};
+use util::common::ErrorReported;
 use util::nodemap::FxHashSet;
 
 use std::iter;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub trait AstConv<'gcx, 'tcx> {
@@ -117,8 +115,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
                     def_id: tcx.hir.local_def_id(id),
-                    index: index,
-                    name: name
+                    index,
+                    name,
                 }))
             }
 
@@ -152,21 +150,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
     {
-        let tcx = self.tcx();
-
-        match item_segment.parameters {
-            hir::AngleBracketedParameters(_) => {}
-            hir::ParenthesizedParameters(..) => {
-                self.prohibit_parenthesized_params(item_segment, true);
-
-                return Substs::for_item(tcx, def_id, |_, _| {
-                    tcx.types.re_static
-                }, |_, _| {
-                    tcx.types.err
-                });
-            }
-        }
-
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_path(span,
                                             def_id,
@@ -196,19 +179,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                parameters={:?})",
                def_id, self_ty, parameters);
 
-        let (lifetimes, num_types_provided, infer_types) = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                (&data.lifetimes[..], data.types.len(), data.infer_types)
-            }
-            hir::ParenthesizedParameters(_) => (&[][..], 1, false)
-        };
-
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
         let decl_generics = tcx.generics_of(def_id);
+        let num_types_provided = parameters.types.len();
         let expected_num_region_params = decl_generics.regions.len();
-        let supplied_num_region_params = lifetimes.len();
+        let supplied_num_region_params = parameters.lifetimes.len();
         if expected_num_region_params != supplied_num_region_params {
             report_lifetime_number_error(tcx, span,
                                          supplied_num_region_params,
@@ -220,7 +197,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 !infer_types || num_types_provided > ty_param_defs.len() {
+        if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
             check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
         }
 
@@ -237,10 +214,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             false
         };
 
-        let mut output_assoc_binding = None;
         let substs = Substs::for_item(tcx, def_id, |def, _| {
             let i = def.index as usize - self_ty.is_some() as usize;
-            if let Some(lifetime) = lifetimes.get(i) {
+            if let Some(lifetime) = parameters.lifetimes.get(i) {
                 self.ast_region_to_region(lifetime, Some(def))
             } else {
                 tcx.types.re_static
@@ -256,18 +232,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
             if i < num_types_provided {
                 // A provided type parameter.
-                match *parameters {
-                    hir::AngleBracketedParameters(ref data) => {
-                        self.ast_ty_to_ty(&data.types[i])
-                    }
-                    hir::ParenthesizedParameters(ref data) => {
-                        assert_eq!(i, 0);
-                        let (ty, assoc) = self.convert_parenthesized_parameters(data);
-                        output_assoc_binding = Some(assoc);
-                        ty
-                    }
-                }
-            } else if infer_types {
+                self.ast_ty_to_ty(&parameters.types[i])
+            } else if parameters.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)
@@ -306,24 +272,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             }
         });
 
-        let assoc_bindings = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                data.bindings.iter().map(|b| {
-                    ConvertedBinding {
-                        item_name: b.name,
-                        ty: self.ast_ty_to_ty(&b.ty),
-                        span: b.span
-                    }
-                }).collect()
-            }
-            hir::ParenthesizedParameters(ref data) => {
-                vec![output_assoc_binding.unwrap_or_else(|| {
-                    // This is an error condition, but we should
-                    // get the associated type binding anyway.
-                    self.convert_parenthesized_parameters(data).1
-                })]
+        let assoc_bindings = parameters.bindings.iter().map(|binding| {
+            ConvertedBinding {
+                item_name: binding.name,
+                ty: self.ast_ty_to_ty(&binding.ty),
+                span: binding.span,
             }
-        };
+        }).collect();
 
         debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
                decl_generics, self_ty, substs);
@@ -331,32 +286,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         (substs, assoc_bindings)
     }
 
-    fn convert_parenthesized_parameters(&self,
-                                        data: &hir::ParenthesizedParameterData)
-                                        -> (Ty<'tcx>, ConvertedBinding<'tcx>)
-    {
-        let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
-            self.ast_ty_to_ty(a_t)
-        }));
-
-        let (output, output_span) = match data.output {
-            Some(ref output_ty) => {
-                (self.ast_ty_to_ty(output_ty), output_ty.span)
-            }
-            None => {
-                (self.tcx().mk_nil(), data.span)
-            }
-        };
-
-        let output_binding = ConvertedBinding {
-            item_name: Symbol::intern(FN_OUTPUT_NAME),
-            ty: output,
-            span: output_span
-        };
-
-        (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
-    }
-
     /// Instantiates the path for the given trait reference, assuming that it's
     /// bound to a valid trait type. Returns the def_id for the defining trait.
     /// Fails if the type is a type other than a trait type.
@@ -453,29 +382,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
         let trait_def = self.tcx().trait_def(trait_def_id);
 
-        match trait_segment.parameters {
-            hir::AngleBracketedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        the precise format of `Fn`-family traits' \
-                        type parameters is subject to change. \
-                        Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
-                }
-            }
-            hir::ParenthesizedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        parenthetical notation is only stable when used with `Fn`-family traits");
-                }
-            }
+        if !self.tcx().sess.features.borrow().unboxed_closures &&
+           trait_segment.parameters.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. \
+                 Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"
+            } else {
+                "parenthetical notation is only stable when used with `Fn`-family traits"
+            };
+            emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures",
+                             span, GateIssue::Language, msg);
         }
 
         self.create_substs_for_ast_path(span,
@@ -951,18 +868,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
 
     pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
         for segment in segments {
-            if let hir::ParenthesizedParameters(_) = segment.parameters {
-                self.prohibit_parenthesized_params(segment, false);
-                break;
-            }
-            for typ in segment.parameters.types() {
+            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() {
+            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,
@@ -970,28 +883,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     .emit();
                 break;
             }
-            for binding in segment.parameters.bindings() {
+            for binding in &segment.parameters.bindings {
                 self.prohibit_projection(binding.span);
                 break;
             }
         }
     }
 
-    pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_error: bool) {
-        if let hir::ParenthesizedParameters(ref data) = segment.parameters {
-            if emit_error {
-                struct_span_err!(self.tcx().sess, data.span, E0214,
-                          "parenthesized parameters may only be used with a trait")
-                    .span_label(data.span, "only traits may use parentheses")
-                    .emit();
-            } else {
-                let msg = "parenthesized parameters may only be used with a trait";
-                self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-                                     ast::CRATE_NODE_ID, data.span, msg);
-            }
-        }
-    }
-
     pub fn prohibit_projection(&self, span: Span) {
         let mut err = struct_span_err!(self.tcx().sess, span, E0229,
                                        "associated type bindings are not allowed here");
@@ -1392,13 +1290,13 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     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() {
+                    if !parameters.types.is_empty() {
                         check_type_argument_count(tcx, bound.trait_ref.path.span,
-                                                  parameters.types().len(), &[]);
+                                                  parameters.types.len(), &[]);
                     }
-                    if !parameters.lifetimes().is_empty() {
+                    if !parameters.lifetimes.is_empty() {
                         report_lifetime_number_error(tcx, bound.trait_ref.path.span,
-                                                     parameters.lifetimes().len(), 0);
+                                                     parameters.lifetimes.len(), 0);
                     }
                     true
                 } else {
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 6aac9dc42ee..e0e946a9c63 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             cur_ty: self.resolve_type_vars_if_possible(&base_ty),
             obligations: vec![],
             at_start: true,
-            span: span,
+            span,
         }
     }
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index b18b11f3d90..9c6cacb9d25 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -136,12 +136,12 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                span: Span)
                -> Result<CastCheck<'tcx>, ErrorReported> {
         let check = CastCheck {
-            expr: expr,
-            expr_ty: expr_ty,
-            expr_diverges: expr_diverges,
-            cast_ty: cast_ty,
-            cast_span: cast_span,
-            span: span,
+            expr,
+            expr_ty,
+            expr_diverges,
+            cast_ty,
+            cast_span,
+            span,
         };
 
         // For better error messages, check for some obviously unsized
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 53f3d811fae..e406ce845a6 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -128,8 +128,8 @@ fn success<'tcx>(adj: Vec<Adjustment<'tcx>>,
 impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
     fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
         Coerce {
-            fcx: fcx,
-            cause: cause,
+            fcx,
+            cause,
             use_lub: false,
         }
     }
@@ -807,8 +807,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let lub_ty = self.commit_if_ok(|_| {
                 self.at(cause, self.param_env)
                     .lub(prev_ty, new_ty)
-                    .map(|ok| self.register_infer_ok_obligations(ok))
-            });
+            }).map(|ok| self.register_infer_ok_obligations(ok));
 
             if lub_ty.is_ok() {
                 // We have a LUB of prev_ty and new_ty, just return it.
@@ -884,8 +883,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 return self.commit_if_ok(|_| {
                     self.at(cause, self.param_env)
                         .lub(prev_ty, new_ty)
-                        .map(|ok| self.register_infer_ok_obligations(ok))
-                });
+                }).map(|ok| self.register_infer_ok_obligations(ok));
             }
         }
 
@@ -898,8 +896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     self.commit_if_ok(|_| {
                         self.at(cause, self.param_env)
                             .lub(prev_ty, new_ty)
-                            .map(|ok| self.register_infer_ok_obligations(ok))
-                    })
+                    }).map(|ok| self.register_infer_ok_obligations(ok))
                 }
             }
             Ok(ok) => {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 355e6cdbbe0..db383b6305b 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -69,10 +69,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
            call_expr: &'gcx hir::Expr)
            -> ConfirmContext<'a, 'gcx, 'tcx> {
         ConfirmContext {
-            fcx: fcx,
-            span: span,
-            self_expr: self_expr,
-            call_expr: call_expr,
+            fcx,
+            span,
+            self_expr,
+            call_expr,
         }
     }
 
@@ -311,17 +311,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        let (supplied_types, supplied_lifetimes) = match segment.parameters {
-            hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
-            _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
-        };
         assert_eq!(method_generics.parent_count(), parent_substs.len());
+        let provided = &segment.parameters;
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.region_at(i)
-            } else if let Some(lifetime) =
-                    supplied_lifetimes.get(i - parent_substs.len()) {
+            } else if let Some(lifetime)
+                    = provided.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)
@@ -330,8 +327,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.type_at(i)
-            } else if let Some(ast_ty) =
-                    supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
+            } else if let Some(ast_ty)
+                    = provided.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 a1c987f22e0..819f48a1b57 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -27,8 +27,6 @@ use rustc::hir;
 pub use self::MethodError::*;
 pub use self::CandidateSource::*;
 
-pub use self::suggest::AllTraitsVec;
-
 mod confirm;
 pub mod probe;
 mod suggest;
@@ -83,10 +81,10 @@ impl<'tcx> NoMatchData<'tcx> {
                mode: probe::Mode)
                -> Self {
         NoMatchData {
-            static_candidates: static_candidates,
-            unsatisfied_predicates: unsatisfied_predicates,
-            out_of_scope_traits: out_of_scope_traits,
-            mode: mode,
+            static_candidates,
+            unsatisfied_predicates,
+            out_of_scope_traits,
+            mode,
         }
     }
 }
@@ -331,7 +329,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                  ty::Predicate::WellFormed(method_ty)));
 
         let callee = MethodCallee {
-            def_id: def_id,
+            def_id,
             substs: trait_ref.substs,
             sig: fn_sig,
         };
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 5de4a35bdc7..096b778cab2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
         } else {
             vec![CandidateStep {
-                     self_ty: self_ty,
+                     self_ty,
                      autoderefs: 0,
                      unsize: false,
                  }]
@@ -361,15 +361,15 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
            opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
            -> ProbeContext<'a, 'gcx, 'tcx> {
         ProbeContext {
-            fcx: fcx,
-            span: span,
-            mode: mode,
-            looking_for: looking_for,
+            fcx,
+            span,
+            mode,
+            looking_for,
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
             impl_dups: FxHashSet(),
             steps: Rc::new(steps),
-            opt_simplified_steps: opt_simplified_steps,
+            opt_simplified_steps,
             static_candidates: Vec::new(),
             private_candidate: None,
             unsatisfied_predicates: Vec::new(),
@@ -719,6 +719,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 continue;
             }
 
+            self.assemble_builtin_candidates(import_id, trait_def_id, item.clone());
+
             self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id,
                                                                item.clone());
 
@@ -732,6 +734,49 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         Ok(())
     }
 
+    fn assemble_builtin_candidates(&mut self,
+                                   import_id: Option<ast::NodeId>,
+                                   trait_def_id: DefId,
+                                   item: ty::AssociatedItem) {
+        if Some(trait_def_id) == self.tcx.lang_items.clone_trait() {
+            self.assemble_builtin_clone_candidates(import_id, trait_def_id, item);
+        }
+    }
+
+    fn assemble_builtin_clone_candidates(&mut self,
+                                         import_id: Option<ast::NodeId>,
+                                         trait_def_id: DefId,
+                                         item: ty::AssociatedItem) {
+        for step in Rc::clone(&self.steps).iter() {
+            match step.self_ty.sty {
+                ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
+                ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
+                ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+                ty::TyRawPtr(..) | ty::TyError | ty::TyNever |
+                ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) |
+                ty::TyArray(..) | ty::TyTuple(..) => {
+                    ()
+                }
+
+                _ => continue,
+            };
+
+            let substs = Substs::for_item(self.tcx,
+                                          trait_def_id,
+                                          |def, _| self.region_var_for_def(self.span, def),
+                                          |def, substs| {
+                if def.index == 0 {
+                    step.self_ty
+                } else {
+                    self.type_var_for_def(self.span, def, substs)
+                }
+            });
+
+            let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
+            self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id);
+        }
+    }
+
     fn assemble_extension_candidates_for_trait_impls(&mut self,
                                                      import_id: Option<ast::NodeId>,
                                                      trait_def_id: DefId,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 56eacc3194d..c8b828f3a43 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -260,6 +260,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 if !static_sources.is_empty() {
                     err.note("found the following associated functions; to be used as methods, \
                               functions must have a `self` parameter");
+                    err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name));
 
                     report_candidates(&mut err, static_sources);
                 }
@@ -584,7 +585,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a>
     let borrow = tcx.all_traits.borrow();
     assert!(borrow.is_some());
     AllTraits {
-        borrow: borrow,
+        borrow,
         idx: 0,
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1b56044710b..955171203e1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -393,8 +393,8 @@ impl UnsafetyState {
                     hir::DefaultBlock =>
                         (unsafety, self.def, self.unsafe_push_count),
                 };
-                UnsafetyState{ def: def,
-                               unsafety: unsafety,
+                UnsafetyState{ def,
+                               unsafety,
                                unsafe_push_count: count,
                                from_fn: false }
             }
@@ -609,7 +609,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
             tables: MaybeInProgressTables {
                 maybe_tables: infcx.in_progress_tables,
             },
-            infcx: infcx,
+            infcx,
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
             locals: RefCell::new(NodeMap()),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
@@ -1646,11 +1646,10 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>)
                                         -> Ty<'tcx>
     {
-        let item = self.tcx().associated_item(item_def_id);
         let (trait_ref, _) =
             self.replace_late_bound_regions_with_fresh_var(
                 span,
-                infer::LateBoundRegionConversionTime::AssocTypeProjection(item.name),
+                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
                 &poly_trait_ref);
 
         self.tcx().mk_projection(item_def_id, trait_ref.substs)
@@ -1697,7 +1696,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                body_id: ast::NodeId)
                -> FnCtxt<'a, 'gcx, 'tcx> {
         FnCtxt {
-            body_id: body_id,
+            body_id,
             param_env,
             err_count_on_creation: inh.tcx.sess.err_count(),
             ret_coercion: None,
@@ -1709,7 +1708,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 stack: Vec::new(),
                 by_id: NodeMap(),
             }),
-            inh: inh,
+            inh,
         }
     }
 
@@ -2968,8 +2967,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             type_error_struct!(self.tcx().sess, field.span, expr_t, E0615,
                               "attempted to take value of method `{}` on type `{}`",
                               field.node, expr_t)
-                .help("maybe a `()` to call it is missing? \
-                       If not, try an anonymous function")
+                .help("maybe a `()` to call it is missing?")
                 .emit();
             self.tcx().types.err
         } else {
@@ -3783,7 +3781,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
               };
 
               let ctxt = BreakableCtxt {
-                  coerce: coerce,
+                  coerce,
                   may_break: false, // will get updated if/when we find a `break`
               };
 
@@ -4622,11 +4620,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 i -= fn_start;
                 fn_segment
             };
-            let lifetimes = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => &[]
-            };
+            let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
 
             if let Some(lifetime) = lifetimes.get(i) {
                 AstConv::ast_region_to_region(self, lifetime, Some(def))
@@ -4649,13 +4643,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 i -= fn_start;
                 fn_segment
             };
-            let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.types[..], data.infer_types)
-                }
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => (&[][..], true)
-            };
+            let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
+                (&s.parameters.types[..], s.parameters.infer_types)
+            });
 
             // Skip over the lifetimes in the same segment.
             if let Some((_, generics)) = segment {
@@ -4729,19 +4719,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                   span: Span,
                                   segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
                                   is_method_call: bool) {
-        let (lifetimes, types, infer_types, bindings) = {
-            match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..])
-                }
-                Some(&hir::ParenthesizedParameters(_)) => {
-                    AstConv::prohibit_parenthesized_params(self, &segment.as_ref().unwrap().0,
-                                                           false);
-                    (&[][..], &[][..], true, &[][..])
-                }
-                None => (&[][..], &[][..], true, &[][..])
-            }
-        };
+        let (lifetimes, types, infer_types, bindings) = segment.map_or(
+            (&[][..], &[][..], true, &[][..]),
+            |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
+                      s.parameters.infer_types, &s.parameters.bindings[..]));
         let infer_lifetimes = lifetimes.len() == 0;
 
         let count_lifetime_params = |n| {
@@ -4787,9 +4768,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
 
         if !bindings.is_empty() {
-            span_err!(self.tcx.sess, bindings[0].span, E0182,
-                      "unexpected binding of associated item in expression path \
-                       (only allowed in type paths)");
+            AstConv::prohibit_projection(self, bindings[0].span);
         }
 
         // Check provided lifetime parameters.
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index b187075a36d..fdbdf925e4c 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                Subject(subject): Subject) -> RegionCtxt<'a, 'gcx, 'tcx> {
         let region_maps = fcx.tcx.region_maps(subject);
         RegionCtxt {
-            fcx: fcx,
-            region_maps: region_maps,
+            fcx,
+            region_maps,
             repeating_scope: initial_repeating_scope,
             body_id: initial_body_id,
             call_site_scope: None,
@@ -1805,8 +1805,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                     let (outlives, _) =
                         self.replace_late_bound_regions_with_fresh_var(
                             span,
-                            infer::AssocTypeProjection(
-                                self.tcx.associated_item(projection_ty.item_def_id).name),
+                            infer::AssocTypeProjection(projection_ty.item_def_id),
                             &outlives);
 
                     debug!("projection_bounds: outlives={:?} (3)",
@@ -1815,12 +1814,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                     // check whether this predicate applies to our current projection
                     let cause = self.fcx.misc(span);
                     match self.at(&cause, self.fcx.param_env).eq(outlives.0, ty) {
-                        Ok(ok) => {
-                            self.register_infer_ok_obligations(ok);
-                            Ok(outlives.1)
-                        }
-                        Err(_) => { Err(()) }
+                        Ok(ok) => Ok((ok, outlives.1)),
+                        Err(_) => Err(())
                     }
+                }).map(|(ok, result)| {
+                    self.register_infer_ok_obligations(ok);
+                    result
                 });
 
                 debug!("projection_bounds: region_result={:?}",
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 31e14a6b630..69f045ab4e9 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -54,7 +54,7 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
             let fcx = FnCtxt::new(&inh, param_env, id);
             let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
                 tcx: fcx.tcx.global_tcx(),
-                code: code
+                code,
             });
             fcx.select_all_obligations_or_error();
             fcx.regionck_item(id, span, &wf_tys);
@@ -66,7 +66,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
     pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
                -> CheckTypeWellFormedVisitor<'a, 'gcx> {
         CheckTypeWellFormedVisitor {
-            tcx: tcx,
+            tcx,
             code: ObligationCauseCode::MiscObligation
         }
     }
@@ -211,8 +211,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
         CheckWfFcxBuilder {
             inherited: Inherited::build(self.tcx, def_id),
             code: self.code.clone(),
-            id: id,
-            span: span,
+            id,
+            span,
             param_env: self.tcx.param_env(def_id),
         }
     }
@@ -233,7 +233,10 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                         fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
                         traits::ObligationCause::new(field.span,
                                                      fcx.body_id,
-                                                     traits::FieldSized));
+                                                     traits::FieldSized(match item.node.adt_kind() {
+                                                        Some(i) => i,
+                                                        None => bug!(),
+                                                     })));
                 }
 
                 // All field types must be well-formed.
@@ -471,7 +474,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
             ExplicitSelf::ByReference(region, mutbl) => {
                 fcx.tcx.mk_ref(region, ty::TypeAndMut {
                     ty: self_ty,
-                    mutbl: mutbl
+                    mutbl,
                 })
             }
             ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty)
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index a363e47a14f..36c72fc4b19 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -80,9 +80,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id);
 
         WritebackCx {
-            fcx: fcx,
+            fcx,
             tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))),
-            body: body
+            body,
         }
     }
 
@@ -445,8 +445,8 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
         Resolver {
             tcx: fcx.tcx,
             infcx: fcx,
-            span: span,
-            body: body,
+            span,
+            body,
         }
     }
 
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index e95d49f00bf..3da154e0689 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -72,4 +72,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let mut visitor = CheckVisitor { tcx, used_trait_imports };
     tcx.hir.krate().visit_all_item_likes(&mut visitor);
+
+    for &(id, span) in &tcx.maybe_unused_extern_crates {
+        let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id();
+        if !tcx.is_compiler_builtins(cnum)
+            && !tcx.is_panic_runtime(cnum)
+            && !tcx.has_global_allocator(cnum) {
+                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
+                let msg = "unused extern crate";
+                tcx.lint_node(lint, id, span, msg);
+            }
+    }
 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 91b41eb33a1..ea86c570c82 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -185,8 +185,8 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
            -> ItemCtxt<'a,'tcx> {
         ItemCtxt {
-            tcx: tcx,
-            item_def_id: item_def_id,
+            tcx,
+            item_def_id,
         }
     }
 }
@@ -630,10 +630,10 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }).collect();
     ty::VariantDef {
-        did: did,
-        name: name,
-        discr: discr,
-        fields: fields,
+        did,
+        name,
+        discr,
+        fields,
         ctor_kind: CtorKind::from_hir(def),
     }
 }
@@ -1028,7 +1028,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             types.extend(fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
                 index: type_start + i as u32,
                 name: Symbol::intern("<upvar>"),
-                def_id: def_id,
+                def_id,
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
                 pure_wrt_drop: false,
@@ -1043,11 +1043,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     tcx.alloc_generics(ty::Generics {
         parent: parent_def_id,
-        parent_regions: parent_regions,
-        parent_types: parent_types,
-        regions: regions,
-        types: types,
-        type_param_to_index: type_param_to_index,
+        parent_regions,
+        parent_types,
+        regions,
+        types,
+        type_param_to_index,
         has_self: has_self || parent_has_self,
         has_late_bound_regions: has_late_bound_regions(tcx, node),
     })
@@ -1382,7 +1382,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                 ItemTrait(_, ref generics, .., ref items) => {
                     is_trait = Some((ty::TraitRef {
-                        def_id: def_id,
+                        def_id,
                         substs: Substs::identity_for_item(tcx, def_id)
                     }, items));
                     generics
@@ -1441,7 +1441,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     for param in early_bound_lifetimes_from_generics(tcx, ast_generics) {
         let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             def_id: tcx.hir.local_def_id(param.lifetime.id),
-            index: index,
+            index,
             name: param.lifetime.name
         }));
         index += 1;
@@ -1560,7 +1560,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     ty::GenericPredicates {
         parent: generics.parent,
-        predicates: predicates
+        predicates,
     }
 }
 
@@ -1611,10 +1611,10 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
     };
 
     Bounds {
-        region_bounds: region_bounds,
-        implicitly_sized: implicitly_sized,
-        trait_bounds: trait_bounds,
-        projection_bounds: projection_bounds,
+        region_bounds,
+        implicitly_sized,
+        trait_bounds,
+        projection_bounds,
     }
 }
 
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 37cb1f9280b..09c7487e635 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -48,7 +48,7 @@ pub fn parameters_for<'tcx, T>(t: &T,
 
     let mut collector = ParameterCollector {
         parameters: vec![],
-        include_nonconstraining: include_nonconstraining
+        include_nonconstraining,
     };
     t.visit_with(&mut collector);
     collector.parameters
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index c74dc24ddc3..cb430efd950 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1636,45 +1636,6 @@ fn bar(foo: Foo) -> u32 {
 ```
 "##,
 
-E0182: r##"
-You bound an associated type in an expression path which is not
-allowed.
-
-Erroneous code example:
-
-```compile_fail,E0182
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-// error: unexpected binding of associated item in expression path
-let x: isize = Foo::<A=usize>::bar();
-```
-
-To give a concrete type when using the Universal Function Call Syntax,
-use "Type as Trait". Example:
-
-```
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-let x: isize = <isize as Foo>::bar(); // ok!
-```
-"##,
-
 E0184: r##"
 Explicitly implementing both Drop and Copy for a type is currently disallowed.
 This feature can make some sense in theory, but the current implementation is
@@ -2359,21 +2320,6 @@ impl Foo {
 "##,
      */
 
-E0214: r##"
-A generic type was described using parentheses rather than angle brackets. For
-example:
-
-```compile_fail,E0214
-fn main() {
-    let v: Vec(&str) = vec!["foo"];
-}
-```
-
-This is not currently supported: `v` should be defined as `Vec<&str>`.
-Parentheses are currently only used with generic types when defining parameters
-for `Fn`-family traits.
-"##,
-
 E0220: r##"
 You used an associated type which isn't defined in the trait.
 Erroneous code example:
@@ -4721,6 +4667,7 @@ register_diagnostics! {
 //  E0172, // non-trait found in a type sum, moved to resolve
 //  E0173, // manual implementations of unboxed closure traits are experimental
 //  E0174,
+//  E0182, // merged into E0229
     E0183,
 //  E0187, // can't infer the kind of the closure
 //  E0188, // can not cast an immutable reference to a mutable pointer
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 9b829e6e3ff..86feea13b17 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -63,9 +63,6 @@ This API is completely unstable and subject to change.
 
 */
 
-#![crate_name = "rustc_typeck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -95,12 +92,11 @@ extern crate rustc_const_math;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
 
-pub use rustc::dep_graph;
-pub use rustc::hir;
-pub use rustc::lint;
-pub use rustc::middle;
-pub use rustc::session;
-pub use rustc::util;
+use rustc::hir;
+use rustc::lint;
+use rustc::middle;
+use rustc::session;
+use rustc::util;
 
 use hir::map as hir_map;
 use rustc::infer::InferOk;
@@ -118,7 +114,7 @@ use syntax_pos::Span;
 use std::iter;
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
-pub mod diagnostics;
+mod diagnostics;
 
 mod check;
 mod check_unused;
@@ -130,8 +126,8 @@ mod coherence;
 mod variance;
 
 pub struct TypeAndSubsts<'tcx> {
-    pub substs: &'tcx Substs<'tcx>,
-    pub ty: Ty<'tcx>,
+    substs: &'tcx Substs<'tcx>,
+    ty: Ty<'tcx>,
 }
 
 fn require_c_abi_if_variadic(tcx: TyCtxt,
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 4b0db749964..40474a7933f 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -73,11 +73,11 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
     let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant));
     let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant));
     let mut constraint_cx = ConstraintContext {
-        terms_cx: terms_cx,
-        covariant: covariant,
-        contravariant: contravariant,
-        invariant: invariant,
-        bivariant: bivariant,
+        terms_cx,
+        covariant,
+        contravariant,
+        invariant,
+        bivariant,
         constraints: Vec::new(),
         dependencies: TransitiveRelation::new(),
     };
@@ -213,7 +213,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         debug!("add_constraint(index={}, variance={:?})", index, variance);
         self.constraints.push(Constraint {
             inferred: InferredIndex(current.inferred_start.0 + index as usize),
-            variance: variance,
+            variance,
         });
     }
 
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 38457146a97..c624b11c5ec 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -79,8 +79,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
                                                      arena: &'a mut TypedArena<VarianceTerm<'a>>)
                                                      -> TermsContext<'a, 'tcx> {
     let mut terms_cx = TermsContext {
-        tcx: tcx,
-        arena: arena,
+        tcx,
+        arena,
         inferred_starts: NodeMap(),
         inferred_terms: vec![],
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 9b4c4e479d0..5d39d1d27f4 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -102,7 +102,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
         source: cx.tcx.def_span(did).clean(cx),
         name: Some(name.clean(cx)),
         attrs: load_attrs(cx, did),
-        inner: inner,
+        inner,
         visibility: Some(clean::Public),
         stability: cx.tcx.lookup_stability(did).clean(cx),
         deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
@@ -142,7 +142,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     clean::Trait {
         unsafety: cx.tcx.trait_def(did).unsafety,
-        generics: generics,
+        generics,
         items: trait_items,
         bounds: supertrait_bounds,
     }
@@ -162,7 +162,7 @@ fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
         decl: (did, sig).clean(cx),
         generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
         unsafety: sig.unsafety(),
-        constness: constness,
+        constness,
         abi: sig.abi(),
     }
 }
@@ -302,7 +302,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
             }),
             source: tcx.def_span(did).clean(cx),
             name: None,
-            attrs: attrs,
+            attrs,
             visibility: Some(clean::Inherited),
             stability: tcx.lookup_stability(did).clean(cx),
             deprecation: tcx.lookup_deprecation(did).clean(cx),
@@ -359,11 +359,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
                         };
 
                         clean::MethodItem(clean::Method {
-                            unsafety: unsafety,
-                            constness: constness,
-                            decl: decl,
-                            generics: generics,
-                            abi: abi
+                            unsafety,
+                            constness,
+                            decl,
+                            generics,
+                            abi,
                         })
                     }
                     ref r => panic!("not a tymethod: {:?}", r),
@@ -414,15 +414,15 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         inner: clean::ImplItem(clean::Impl {
             unsafety: hir::Unsafety::Normal, // FIXME: this should be decoded
             provided_trait_methods: provided,
-            trait_: trait_,
-            for_: for_,
+            trait_,
+            for_,
             generics: (tcx.generics_of(did), &predicates).clean(cx),
             items: trait_items,
             polarity: Some(polarity.clean(cx)),
         }),
         source: tcx.def_span(did).clean(cx),
         name: None,
-        attrs: attrs,
+        attrs,
         visibility: Some(clean::Inherited),
         stability: tcx.lookup_stability(did).clean(cx),
         deprecation: tcx.lookup_deprecation(did).clean(cx),
@@ -434,7 +434,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
     let mut items = Vec::new();
     fill_in(cx, did, &mut items);
     return clean::Module {
-        items: items,
+        items,
         is_crate: false,
     };
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 57e72c3a40b..7d6ad5286d1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -156,7 +156,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     visibility: Some(Public),
                     stability: get_stability(cx, def_id),
                     deprecation: get_deprecation(cx, def_id),
-                    def_id: def_id,
+                    def_id,
                     inner: PrimitiveItem(prim),
                 }
             }));
@@ -166,11 +166,11 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
         let mut external_traits = cx.external_traits.borrow_mut();
 
         Crate {
-            name: name,
-            src: src,
+            name,
+            src,
             module: Some(module),
-            externs: externs,
-            primitives: primitives,
+            externs,
+            primitives,
             access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
             external_traits: mem::replace(&mut external_traits, Default::default()),
         }
@@ -252,7 +252,7 @@ impl Clean<ExternalCrate> for CrateNum {
             name: cx.tcx.crate_name(*self).to_string(),
             src: PathBuf::from(krate_src),
             attrs: cx.tcx.get_attrs(root).clean(cx),
-            primitives: primitives,
+            primitives,
         }
     }
 }
@@ -323,6 +323,10 @@ impl Item {
     pub fn is_union(&self) -> bool {
         self.type_() == ItemType::Union
     }
+    pub fn is_import(&self) -> bool {
+        self.type_() == ItemType::Import
+    }
+
     pub fn is_stripped(&self) -> bool {
         match self.inner { StrippedItem(..) => true, _ => false }
     }
@@ -474,7 +478,7 @@ impl Clean<Item> for doctree::Module {
             def_id: cx.tcx.hir.local_def_id(self.id),
             inner: ModuleItem(Module {
                is_crate: self.is_crate,
-               items: items
+               items,
             })
         }
     }
@@ -519,7 +523,7 @@ impl AttributesExt for [ast::Attribute] {
         ListAttributesIter {
             attrs: self.iter(),
             current_list: Vec::new().into_iter(),
-            name: name
+            name,
         }
     }
 }
@@ -673,9 +677,9 @@ impl TyParamBound {
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
             trait_: ResolvedPath {
-                path: path,
+                path,
                 typarams: None,
-                did: did,
+                did,
                 is_generic: false,
             },
             lifetimes: vec![]
@@ -715,9 +719,9 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
                 ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
                 _ => {
                     return PathParameters::AngleBracketed {
-                        lifetimes: lifetimes,
+                        lifetimes,
                         types: types.clean(cx),
-                        bindings: bindings
+                        bindings,
                     }
                 }
             };
@@ -728,15 +732,15 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
             //     _ => Some(types[1].clean(cx))
             // };
             PathParameters::Parenthesized {
-                inputs: inputs,
-                output: output
+                inputs,
+                output,
             }
         },
         _ => {
             PathParameters::AngleBracketed {
-                lifetimes: lifetimes,
+                lifetimes,
                 types: types.clean(cx),
-                bindings: bindings
+                bindings,
             }
         }
     }
@@ -784,7 +788,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         TraitBound(
             PolyTrait {
                 trait_: ResolvedPath {
-                    path: path,
+                    path,
                     typarams: None,
                     did: self.def_id,
                     is_generic: false,
@@ -1181,7 +1185,7 @@ impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
                     name = "_".to_string();
                 }
                 Argument {
-                    name: name,
+                    name,
                     type_: ty.clean(cx),
                 }
             }).collect()
@@ -1359,7 +1363,7 @@ impl Clean<Item> for hir::TraitItem {
             visibility: None,
             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
-            inner: inner
+            inner,
         }
     }
 }
@@ -1391,7 +1395,7 @@ impl Clean<Item> for hir::ImplItem {
             visibility: self.vis.clean(cx),
             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
-            inner: inner
+            inner,
         }
     }
 }
@@ -1438,8 +1442,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                 if provided {
                     MethodItem(Method {
                         unsafety: sig.unsafety(),
-                        generics: generics,
-                        decl: decl,
+                        generics,
+                        decl,
                         abi: sig.abi(),
 
                         // trait methods cannot (currently, at least) be const
@@ -1448,8 +1452,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                 } else {
                     TyMethodItem(TyMethod {
                         unsafety: sig.unsafety(),
-                        generics: generics,
-                        decl: decl,
+                        generics,
+                        decl,
                         abi: sig.abi(),
                     })
                 }
@@ -1515,7 +1519,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
             def_id: self.def_id,
             attrs: inline::load_attrs(cx, self.def_id),
             source: cx.tcx.def_span(self.def_id).clean(cx),
-            inner: inner,
+            inner,
         }
     }
 }
@@ -1794,16 +1798,14 @@ impl Clean<Type> for hir::Ty {
                     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()
-                                                                        .cloned() {
+                        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()
-                                                                            .cloned() {
+                        if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
                             if !lt.is_elided() {
                                 lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
                             }
@@ -1835,7 +1837,7 @@ impl Clean<Type> for hir::Ty {
                 }
                 let trait_path = hir::Path {
                     span: self.span,
-                    def: def,
+                    def,
                     segments: vec![].into(),
                 };
                 Type::QPath {
@@ -1854,10 +1856,10 @@ impl Clean<Type> for hir::Ty {
                             bounds.push(RegionBound(lifetime.clean(cx)));
                         }
                         ResolvedPath {
-                            path: path,
+                            path,
                             typarams: Some(bounds),
-                            did: did,
-                            is_generic: is_generic,
+                            did,
+                            is_generic,
                         }
                     }
                     _ => Infer // shouldn't happen
@@ -1915,9 +1917,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
                                          None, false, vec![], substs);
                 ResolvedPath {
-                    path: path,
+                    path,
                     typarams: None,
-                    did: did,
+                    did,
                     is_generic: false,
                 }
             }
@@ -1935,9 +1937,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
                             trait_: ResolvedPath {
-                                path: path,
+                                path,
                                 typarams: None,
-                                did: did,
+                                did,
                                 is_generic: false,
                             },
                             lifetimes: vec![]
@@ -1956,9 +1958,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
                         false, bindings, principal.0.substs);
                     ResolvedPath {
-                        path: path,
+                        path,
                         typarams: Some(typarams),
-                        did: did,
+                        did,
                         is_generic: false,
                     }
                 } else {
@@ -2274,7 +2276,7 @@ impl Path {
             global: false,
             def: Def::Err,
             segments: vec![PathSegment {
-                name: name,
+                name,
                 params: PathParameters::AngleBracketed {
                     lifetimes: Vec::new(),
                     types: Vec::new(),
@@ -2314,24 +2316,21 @@ pub enum PathParameters {
 
 impl Clean<PathParameters> for hir::PathParameters {
     fn clean(&self, cx: &DocContext) -> PathParameters {
-        match *self {
-            hir::AngleBracketedParameters(ref data) => {
-                PathParameters::AngleBracketed {
-                    lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                        vec![]
-                    } else {
-                        data.lifetimes.clean(cx)
-                    },
-                    types: data.types.clean(cx),
-                    bindings: data.bindings.clean(cx),
-                }
+        if self.parenthesized {
+            let output = self.bindings[0].ty.clean(cx);
+            PathParameters::Parenthesized {
+                inputs: self.inputs().clean(cx),
+                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
             }
-
-            hir::ParenthesizedParameters(ref data) => {
-                PathParameters::Parenthesized {
-                    inputs: data.inputs.clean(cx),
-                    output: data.output.clean(cx),
-                }
+        } else {
+            PathParameters::AngleBracketed {
+                lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
+                    vec![]
+                } else {
+                    self.lifetimes.clean(cx)
+                },
+                types: self.types.clean(cx),
+                bindings: self.bindings.clean(cx),
             }
         }
     }
@@ -2549,9 +2548,9 @@ impl Clean<Vec<Item>> for doctree::Impl {
                 unsafety: self.unsafety,
                 generics: self.generics.clean(cx),
                 provided_trait_methods: provided,
-                trait_: trait_,
+                trait_,
                 for_: self.for_.clean(cx),
-                items: items,
+                items,
                 polarity: Some(self.polarity.clean(cx)),
             }),
         });
@@ -2745,7 +2744,7 @@ impl Clean<Item> for hir::ForeignItem {
             visibility: self.vis.clean(cx),
             stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)),
             deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)),
-            inner: inner,
+            inner,
         }
     }
 }
@@ -2871,7 +2870,7 @@ fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
         } else {
             Some(register_def(cx, path.def))
         },
-        path: path,
+        path,
     }
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9bb7e4e3a09..58de0e1caec 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -121,18 +121,18 @@ pub fn run_core(search_paths: SearchPaths,
     let warning_lint = lint::builtin::WARNINGS.name_lower();
 
     let sessopts = config::Options {
-        maybe_sysroot: maybe_sysroot,
-        search_paths: search_paths,
+        maybe_sysroot,
+        search_paths,
         crate_types: vec![config::CrateTypeRlib],
         lint_opts: if !allow_warnings { vec![(warning_lint, lint::Allow)] } else { vec![] },
         lint_cap: Some(lint::Allow),
-        externs: externs,
+        externs,
         target_triple: triple.unwrap_or(config::host_triple().to_string()),
         // Ensure that rustdoc works even if rustc is feature-staged
         unstable_features: UnstableFeatures::Allow,
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions {
-            force_unstable_if_unmarked: force_unstable_if_unmarked,
+            force_unstable_if_unmarked,
             ..config::basic_debugging_options()
         },
         ..config::basic_options().clone()
@@ -203,7 +203,7 @@ pub fn run_core(search_paths: SearchPaths,
         };
 
         let ctxt = DocContext {
-            tcx: tcx,
+            tcx,
             populated_all_crate_impls: Cell::new(false),
             access_levels: RefCell::new(access_levels),
             external_traits: Default::default(),
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index e269d940bfa..54c57c9ac6e 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -97,9 +97,8 @@ pub trait DocFolder : Sized {
             _ => self.fold_inner_recur(inner),
         };
 
-        Some(Item { attrs: attrs, name: name, source: source, inner: inner,
-                    visibility: visibility, stability: stability, deprecation: deprecation,
-                    def_id: def_id })
+        Some(Item { attrs, name, source, inner, visibility,
+                    stability, deprecation, def_id })
     }
 
     fn fold_mod(&mut self, m: Module) -> Module {
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 89a40b0db96..eb27fa3abfa 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -106,7 +106,7 @@ pub enum Class {
 }
 
 /// Trait that controls writing the output of syntax highlighting. Users should
-/// implement this trait to customise writing output.
+/// implement this trait to customize writing output.
 ///
 /// The classifier will call into the `Writer` implementation as it finds spans
 /// of text to highlight. Exactly how that text should be highlighted is up to
@@ -164,8 +164,8 @@ impl<U: Write> Writer for U {
 impl<'a> Classifier<'a> {
     pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> {
         Classifier {
-            lexer: lexer,
-            codemap: codemap,
+            lexer,
+            codemap,
             in_attribute: false,
             in_macro: false,
             in_macro_nonterminal: false,
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 82c252ae4d7..2d14c02bf8a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -241,7 +241,7 @@ impl<'a, 'b, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, I> {
     fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self {
         HeadingLinks {
             inner: iter,
-            toc: toc,
+            toc,
             buf: VecDeque::new(),
         }
     }
@@ -1121,15 +1121,15 @@ mod tests {
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
             compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
             assert_eq!(LangString::parse(s), LangString {
-                should_panic: should_panic,
-                no_run: no_run,
-                ignore: ignore,
-                rust: rust,
-                test_harness: test_harness,
-                compile_fail: compile_fail,
-                error_codes: error_codes,
+                should_panic,
+                no_run,
+                ignore,
+                rust,
+                test_harness,
+                compile_fail,
+                error_codes,
                 original: s.to_owned(),
-                allow_fail: allow_fail,
+                allow_fail,
             })
         }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 4e3181759f9..5457f69cb6d 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -443,8 +443,8 @@ pub fn run(mut krate: clean::Crate,
         None => PathBuf::new(),
     };
     let mut scx = SharedContext {
-        src_root: src_root,
-        passes: passes,
+        src_root,
+        passes,
         include_sources: true,
         local_sources: FxHashMap(),
         issue_tracker_base_url: None,
@@ -496,10 +496,10 @@ pub fn run(mut krate: clean::Crate,
     krate = render_sources(&dst, &mut scx, krate)?;
     let cx = Context {
         current: Vec::new(),
-        dst: dst,
+        dst,
         render_redirect_pages: false,
         shared: Arc::new(scx),
-        render_type: render_type,
+        render_type,
     };
 
     // Crawl the crate to build various caches used for the output
@@ -518,7 +518,7 @@ pub fn run(mut krate: clean::Crate,
 
     let mut cache = Cache {
         impls: FxHashMap(),
-        external_paths: external_paths,
+        external_paths,
         paths: FxHashMap(),
         implementors: FxHashMap(),
         stack: Vec::new(),
@@ -531,9 +531,9 @@ pub fn run(mut krate: clean::Crate,
         access_levels: krate.access_levels.clone(),
         orphan_impl_items: Vec::new(),
         traits: mem::replace(&mut krate.external_traits, FxHashMap()),
-        deref_trait_did: deref_trait_did,
-        deref_mut_trait_did: deref_mut_trait_did,
-        owned_box_did: owned_box_did,
+        deref_trait_did,
+        deref_mut_trait_did,
+        owned_box_did,
         typarams: external_typarams,
     };
 
@@ -823,8 +823,8 @@ fn render_sources(dst: &Path, scx: &mut SharedContext,
     let dst = dst.join("src").join(&krate.name);
     try_err!(fs::create_dir_all(&dst), &dst);
     let mut folder = SourceCollector {
-        dst: dst,
-        scx: scx,
+        dst,
+        scx,
     };
     Ok(folder.fold_crate(krate))
 }
@@ -1068,7 +1068,7 @@ impl DocFolder for Cache {
                             name: s.to_string(),
                             path: path.join("::").to_string(),
                             desc: plain_summary_line(item.doc_value()),
-                            parent: parent,
+                            parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
                         });
@@ -1764,6 +1764,37 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
+    // This call is to remove reexport duplicates in cases such as:
+    //
+    // ```
+    // pub mod foo {
+    //     pub mod bar {
+    //         pub trait Double { fn foo(); }
+    //     }
+    // }
+    //
+    // pub use foo::bar::*;
+    // pub use foo::*;
+    // ```
+    //
+    // `Double` will appear twice in the generated docs.
+    //
+    // FIXME: This code is quite ugly and could be improved. Small issue: DefId
+    // can be identical even if the elements are different (mostly in imports).
+    // So in case this is an import, we keep everything by adding a "unique id"
+    // (which is the position in the vector).
+    indices.dedup_by_key(|i| (items[*i].def_id,
+                              if items[*i].name.as_ref().is_some() {
+                                  Some(full_path(cx, &items[*i]).clone())
+                              } else {
+                                  None
+                              },
+                              items[*i].type_(),
+                              if items[*i].is_import() {
+                                  *i
+                              } else {
+                                  0
+                              }));
 
     debug!("{:?}", indices);
     let mut curty = None;
@@ -2038,7 +2069,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
            where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
            decl = Method {
                decl: &f.decl,
-               name_len: name_len,
+               name_len,
                indent: 0,
            })?;
     document(w, cx, it)
@@ -2406,12 +2437,12 @@ fn render_assoc_item(w: &mut fmt::Formatter,
                decl = Method {
                    decl: d,
                    name_len: head_len,
-                   indent: indent,
+                   indent,
                },
                where_clause = WhereClause {
                    gens: g,
-                   indent: indent,
-                   end_newline: end_newline,
+                   indent,
+                   end_newline,
                })
     }
     match item.inner {
@@ -2925,7 +2956,13 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
 fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
                render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result {
     if render_mode == RenderMode::Normal {
-        write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
+        let id = derive_id(match i.inner_impl().trait_ {
+            Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
+            None => "impl".to_string(),
+        });
+        write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
+               id, i.inner_impl())?;
+        write!(w, "<a href='#{}' class='anchor'></a>", id)?;
         write!(w, "</span><span class='out-of-band'>")?;
         let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
         if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index ee94f0baeb9..4a3286b421a 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -126,6 +126,10 @@ p {
 	margin: 0 0 .6em 0;
 }
 
+summary {
+	outline: none;
+}
+
 code, pre {
 	font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
 	white-space: pre-wrap;
@@ -441,6 +445,10 @@ a {
 .small-section-header:hover > .anchor {
 	display: initial;
 }
+
+.in-band:hover > .anchor {
+	display: initial;
+}
 .anchor {
 	display: none;
 }
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css
index 08bf5a10fe9..c5f4272b932 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/styles/main.css
@@ -26,6 +26,7 @@ h1.fqn {
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
 	border-bottom-color: #DDDDDD;
 }
+
 .in-band {
 	background-color: white;
 }
@@ -83,6 +84,11 @@ pre {
 }
 
 :target { background: #FDFFD3; }
+
+:target > .in-band {
+	background: #FDFFD3;
+}
+
 .content .highlighted {
 	color: #000 !important;
 	background-color: #ccc;
diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs
index a7da1c5cca4..f3379b33155 100644
--- a/src/librustdoc/html/toc.rs
+++ b/src/librustdoc/html/toc.rs
@@ -95,7 +95,7 @@ impl TocBuilder {
     /// self.top_level, D is in C.children, and C, E, F, G are in
     /// self.chain.
     ///
-    /// When we attempt to push H, we realise that first G is not the
+    /// When we attempt to push H, we realize that first G is not the
     /// parent (level is too high) so it is popped from chain and put
     /// into F.children, then F isn't the parent (level is equal, aka
     /// sibling), so it's also popped and put into E.children.
@@ -161,10 +161,10 @@ impl TocBuilder {
         }
 
         self.chain.push(TocEntry {
-            level: level,
-            name: name,
-            sec_number: sec_number,
-            id: id,
+            level,
+            name,
+            sec_number,
+            id,
             children: Toc { entries: Vec::new() }
         });
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 9264015ed9e..61a8165d26a 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustdoc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/",
@@ -400,7 +397,7 @@ pub fn main_args(args: &[String]) -> isize {
     })
 }
 
-/// Prints an uniformised error message on the standard error output
+/// Prints an uniformized error message on the standard error output
 fn print_error<T>(error_message: T) where T: Display {
     writeln!(
         &mut io::stderr(),
diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs
index a38ef2b2518..4fc5159588d 100644
--- a/src/librustdoc/plugins.rs
+++ b/src/librustdoc/plugins.rs
@@ -35,7 +35,7 @@ impl PluginManager {
         PluginManager {
             dylibs: Vec::new(),
             callbacks: Vec::new(),
-            prefix: prefix,
+            prefix,
         }
     }
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index b1fb343b8bb..47e8d63f80a 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -194,7 +194,7 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs
         search_paths: libs,
         crate_types: vec![config::CrateTypeExecutable],
         output_types: outputs,
-        externs: externs,
+        externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
             .. config::basic_codegen_options()
@@ -416,19 +416,19 @@ impl Collector {
             tests: Vec::new(),
             old_tests: HashMap::new(),
             names: Vec::new(),
-            cfgs: cfgs,
-            libs: libs,
-            externs: externs,
+            cfgs,
+            libs,
+            externs,
             cnt: 0,
-            use_headers: use_headers,
+            use_headers,
             current_header: None,
-            cratename: cratename,
-            opts: opts,
-            maybe_sysroot: maybe_sysroot,
+            cratename,
+            opts,
+            maybe_sysroot,
             position: DUMMY_SP,
-            codemap: codemap,
-            filename: filename,
-            render_type: render_type,
+            codemap,
+            filename,
+            render_type,
         }
     }
 
@@ -499,7 +499,7 @@ impl Collector {
                 ignore: should_ignore,
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
-                allow_fail: allow_fail,
+                allow_fail,
             },
             testfn: testing::DynTestFn(box move |()| {
                 let panic = io::set_panic(None);
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 657aab958bb..e3426fba1bc 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -58,7 +58,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         RustdocVisitor {
             module: Module::new(None),
             attrs: hir::HirVec::new(),
-            cx: cx,
+            cx,
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
@@ -99,8 +99,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let struct_type = struct_type_from_def(&*sd);
         Struct {
             id: item.id,
-            struct_type: struct_type,
-            name: name,
+            struct_type,
+            name,
             vis: item.vis.clone(),
             stab: self.stability(item.id),
             depr: self.deprecation(item.id),
@@ -118,8 +118,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let struct_type = struct_type_from_def(&*sd);
         Union {
             id: item.id,
-            struct_type: struct_type,
-            name: name,
+            struct_type,
+            name,
             vis: item.vis.clone(),
             stab: self.stability(item.id),
             depr: self.deprecation(item.id),
@@ -135,7 +135,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                           params: &hir::Generics) -> Enum {
         debug!("Visiting enum");
         Enum {
-            name: name,
+            name,
             variants: def.variants.iter().map(|v| Variant {
                 name: v.node.name,
                 attrs: v.node.attrs.clone(),
@@ -169,13 +169,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             depr: self.deprecation(item.id),
             attrs: item.attrs.clone(),
             decl: fd.clone(),
-            name: name,
+            name,
             whence: item.span,
             generics: gen.clone(),
             unsafety: *unsafety,
-            constness: constness,
+            constness,
             abi: *abi,
-            body: body,
+            body,
         }
     }
 
@@ -221,11 +221,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     };
 
                     om.macros.push(Macro {
-                        def_id: def_id,
+                        def_id,
                         attrs: def.attrs.clone().into(),
                         name: def.ident.name,
                         whence: def.span,
-                        matchers: matchers,
+                        matchers,
                         stab: self.stability(def.id),
                         depr: self.deprecation(def.id),
                         imported_from: Some(imported_from),
@@ -374,7 +374,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.extern_crates.push(ExternCrate {
                     cnum: cstore.extern_mod_stmt_cnum(item.id)
                                 .unwrap_or(LOCAL_CRATE),
-                    name: name,
+                    name,
                     path: p.map(|x|x.to_string()),
                     vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
@@ -408,7 +408,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 }
 
                 om.imports.push(Import {
-                    name: name,
+                    name,
                     id: item.id,
                     vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
@@ -438,7 +438,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 let t = Typedef {
                     ty: ty.clone(),
                     gen: gen.clone(),
-                    name: name,
+                    name,
                     id: item.id,
                     attrs: item.attrs.clone(),
                     whence: item.span,
@@ -454,7 +454,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     mutability: mut_.clone(),
                     expr: exp.clone(),
                     id: item.id,
-                    name: name,
+                    name,
                     attrs: item.attrs.clone(),
                     whence: item.span,
                     vis: item.vis.clone(),
@@ -468,7 +468,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     type_: ty.clone(),
                     expr: exp.clone(),
                     id: item.id,
-                    name: name,
+                    name,
                     attrs: item.attrs.clone(),
                     whence: item.span,
                     vis: item.vis.clone(),
@@ -482,9 +482,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                                     .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone())
                                     .collect();
                 let t = Trait {
-                    unsafety: unsafety,
-                    name: name,
-                    items: items,
+                    unsafety,
+                    name,
+                    items,
                     generics: gen.clone(),
                     bounds: b.iter().cloned().collect(),
                     id: item.id,
@@ -511,13 +511,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                                         .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone())
                                         .collect();
                     let i = Impl {
-                        unsafety: unsafety,
-                        polarity: polarity,
-                        defaultness: defaultness,
+                        unsafety,
+                        polarity,
+                        defaultness,
                         generics: gen.clone(),
                         trait_: tr.clone(),
                         for_: ty.clone(),
-                        items: items,
+                        items,
                         attrs: item.attrs.clone(),
                         id: item.id,
                         whence: item.span,
@@ -532,7 +532,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 // See comment above about ItemImpl.
                 if !self.inlining {
                     let i = DefaultImpl {
-                        unsafety: unsafety,
+                        unsafety,
                         trait_: trait_ref.clone(),
                         id: item.id,
                         attrs: item.attrs.clone(),
@@ -555,7 +555,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             attrs: def.attrs.clone(),
             name: def.name,
             whence: def.span,
-            matchers: matchers,
+            matchers,
             stab: self.stability(def.id),
             depr: self.deprecation(def.id),
             imported_from: None,
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 5518d854348..7b5b27c5565 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -37,7 +37,7 @@ pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
 impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
     pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 'tcx> {
         LibEmbargoVisitor {
-            cx: cx,
+            cx,
             cstore: &*cx.sess().cstore,
             access_levels: cx.access_levels.borrow_mut(),
             prev_level: Some(AccessLevel::Public),
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index dae0b5f0123..5e1c09641e1 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -717,7 +717,7 @@ impl<'a> PrettyEncoder<'a> {
     /// Creates a new encoder whose output will be written to the specified writer
     pub fn new(writer: &'a mut fmt::Write) -> PrettyEncoder<'a> {
         PrettyEncoder {
-            writer: writer,
+            writer,
             curr_indent: 0,
             indent: 2,
             is_emitting_map_key: false,
@@ -1451,7 +1451,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
     /// Creates the JSON parser.
     pub fn new(rdr: T) -> Parser<T> {
         let mut p = Parser {
-            rdr: rdr,
+            rdr,
             ch: Some('\x00'),
             line: 1,
             col: 0,
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index c3107d1f190..2e354252c15 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -14,9 +14,6 @@
 Core encoding and decoding interfaces.
 */
 
-#![crate_name = "serialize"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs
index 9c3db64d4d8..f3475bd18ce 100644
--- a/src/libserialize/opaque.rs
+++ b/src/libserialize/opaque.rs
@@ -153,8 +153,8 @@ pub struct Decoder<'a> {
 impl<'a> Decoder<'a> {
     pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
         Decoder {
-            data: data,
-            position: position,
+            data,
+            position,
         }
     }
 
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 0b5c2db171d..f57dec98b79 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -21,7 +21,7 @@ fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
-        !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
+        !target.contains("emscripten") && !target.contains("fuchsia") {
         let _ = build_libbacktrace(&host, &target);
     }
 
@@ -30,7 +30,7 @@ fn main() {
             println!("cargo:rustc-link-lib=dl");
             println!("cargo:rustc-link-lib=log");
             println!("cargo:rustc-link-lib=gcc");
-        } else if !target.contains("musl") || target.contains("mips") {
+        } else if !target.contains("musl") {
             println!("cargo:rustc-link-lib=dl");
             println!("cargo:rustc-link-lib=rt");
             println!("cargo:rustc-link-lib=pthread");
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 7e2229a8f84..16b0c709986 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -419,7 +419,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
             Empty(bucket) => {
                 // Found a hole!
                 return InternalEntry::Vacant {
-                    hash: hash,
+                    hash,
                     elem: NoElem(bucket, displacement),
                 };
             }
@@ -433,7 +433,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
             // We can finish the search early if we hit any bucket
             // with a lower distance to initial bucket than we've probed.
             return InternalEntry::Vacant {
-                hash: hash,
+                hash,
                 elem: NeqElem(full, probe_displacement),
             };
         }
@@ -646,7 +646,7 @@ impl<K, V, S> HashMap<K, V, S>
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
     pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
         HashMap {
-            hash_builder: hash_builder,
+            hash_builder,
             resize_policy: DefaultResizePolicy::new(),
             table: RawTable::new(0),
         }
@@ -679,8 +679,8 @@ impl<K, V, S> HashMap<K, V, S>
         let resize_policy = DefaultResizePolicy::new();
         let raw_cap = resize_policy.raw_capacity(capacity);
         HashMap {
-            hash_builder: hash_builder,
-            resize_policy: resize_policy,
+            hash_builder,
+            resize_policy,
             table: RawTable::new(raw_cap),
         }
     }
@@ -1496,14 +1496,14 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> {
             InternalEntry::Occupied { elem } => {
                 Some(Occupied(OccupiedEntry {
                     key: Some(key),
-                    elem: elem,
+                    elem,
                 }))
             }
             InternalEntry::Vacant { hash, elem } => {
                 Some(Vacant(VacantEntry {
-                    hash: hash,
-                    key: key,
-                    elem: elem,
+                    hash,
+                    key,
+                    elem,
                 }))
             }
             InternalEntry::TableIsEmpty => None,
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 80a223c7d74..9771363d545 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -337,7 +337,7 @@ impl<T, S> HashSet<T, S>
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
         Difference {
             iter: self.iter(),
-            other: other,
+            other,
         }
     }
 
@@ -391,7 +391,7 @@ impl<T, S> HashSet<T, S>
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
         Intersection {
             iter: self.iter(),
-            other: other,
+            other,
         }
     }
 
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 6f7c5a5de42..f1e8ff66af1 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -353,14 +353,14 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> Bucket<K, V, M> {
         let ib_index = ib_index & table.capacity_mask;
         Bucket {
             raw: table.raw_bucket_at(ib_index),
-            table: table,
+            table,
         }
     }
 
     pub fn first(table: M) -> Bucket<K, V, M> {
         Bucket {
             raw: table.raw_bucket_at(0),
-            table: table,
+            table,
         }
     }
 
@@ -455,7 +455,7 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> EmptyBucket<K, V, M> {
         match self.next().peek() {
             Full(bucket) => {
                 Ok(GapThenFull {
-                    gap: gap,
+                    gap,
                     full: bucket,
                 })
             }
@@ -860,8 +860,8 @@ impl<K, V> RawTable<K, V> {
         // Replace the marker regardless of lifetime bounds on parameters.
         IntoIter {
             iter: RawBuckets {
-                raw: raw,
-                elems_left: elems_left,
+                raw,
+                elems_left,
                 marker: marker::PhantomData,
             },
             table: self,
@@ -873,8 +873,8 @@ impl<K, V> RawTable<K, V> {
         // Replace the marker regardless of lifetime bounds on parameters.
         Drain {
             iter: RawBuckets {
-                raw: raw,
-                elems_left: elems_left,
+                raw,
+                elems_left,
                 marker: marker::PhantomData,
             },
             table: Shared::from(self),
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index db64d41011c..7392a153e3b 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -830,7 +830,7 @@ impl CStr {
     ///
     /// It is your responsibility to make sure that the underlying memory is not
     /// freed too early. For example, the following code will cause undefined
-    /// behaviour when `ptr` is used inside the `unsafe` block:
+    /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
     /// use std::ffi::{CString};
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index d62e3e905e3..a40a9329ed9 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -123,7 +123,7 @@ impl OsString {
 
     /// Creates a new `OsString` with the given capacity.
     ///
-    /// The string will be able to hold exactly `capacity` lenth units of other
+    /// The string will be able to hold exactly `capacity` length units of other
     /// OS strings without reallocating. If `capacity` is 0, the string will not
     /// allocate.
     ///
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 1e692abaff2..a438b4afdd0 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -916,7 +916,7 @@ impl AsInner<fs_imp::FileAttr> for Metadata {
 }
 
 impl Permissions {
-    /// Returns whether these permissions describe a readonly file.
+    /// Returns whether these permissions describe a readonly (unwritable) file.
     ///
     /// # Examples
     ///
@@ -934,7 +934,11 @@ impl Permissions {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn readonly(&self) -> bool { self.0.readonly() }
 
-    /// Modifies the readonly flag for this set of permissions.
+    /// Modifies the readonly flag for this set of permissions. If the
+    /// `readonly` argument is `true`, using the resulting `Permission` will
+    /// update file permissions to forbid writing. Conversely, if it's `false`,
+    /// using the resulting `Permission` will update file permissions to allow
+    /// writing.
     ///
     /// This operation does **not** modify the filesystem. To modify the
     /// filesystem use the `fs::set_permissions` function.
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index d765dd227be..4ebd3554fd1 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -97,7 +97,7 @@ impl<R: Read> BufReader<R> {
             buffer.set_len(cap);
             inner.initializer().initialize(&mut buffer);
             BufReader {
-                inner: inner,
+                inner,
                 buf: buffer.into_boxed_slice(),
                 pos: 0,
                 cap: 0,
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index d986021a18b..32a92145aaf 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -69,7 +69,7 @@ use io::{self, Initializer, SeekFrom, Error, ErrorKind};
 /// // now let's write a test
 /// #[test]
 /// fn test_writes_bytes() {
-///     // setting up a real File is much more slow than an in-memory buffer,
+///     // setting up a real File is much slower than an in-memory buffer,
 ///     // let's use a cursor instead
 ///     use std::io::Cursor;
 ///     let mut buff = Cursor::new(vec![0; 15]);
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index 68f55221a6c..bb9383d3d6e 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -252,8 +252,8 @@ impl Error {
     fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
         Error {
             repr: Repr::Custom(Box::new(Custom {
-                kind: kind,
-                error: error,
+                kind,
+                error,
             }))
         }
     }
diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs
index ce205c3b11c..9cef4e3cdf1 100644
--- a/src/libstd/io/lazy.rs
+++ b/src/libstd/io/lazy.rs
@@ -27,7 +27,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
         Lazy {
             lock: Mutex::new(),
             ptr: Cell::new(ptr::null_mut()),
-            init: init
+            init,
         }
     }
 
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index f486493f98b..074ab3ebd8f 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -401,28 +401,29 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 ///
 /// Implementors of the `Read` trait are called 'readers'.
 ///
-/// Readers are defined by one required method, `read()`. Each call to `read`
+/// Readers are defined by one required method, [`read()`]. Each call to [`read()`]
 /// will attempt to pull bytes from this source into a provided buffer. A
-/// number of other methods are implemented in terms of `read()`, giving
+/// number of other methods are implemented in terms of [`read()`], giving
 /// implementors a number of ways to read bytes while only needing to implement
 /// a single method.
 ///
 /// Readers are intended to be composable with one another. Many implementors
-/// throughout `std::io` take and provide types which implement the `Read`
+/// throughout [`std::io`] take and provide types which implement the `Read`
 /// trait.
 ///
-/// Please note that each call to `read` may involve a system call, and
-/// therefore, using something that implements [`BufRead`][bufread], such as
-/// [`BufReader`][bufreader], will be more efficient.
-///
-/// [bufread]: trait.BufRead.html
-/// [bufreader]: struct.BufReader.html
+/// Please note that each call to [`read()`] may involve a system call, and
+/// therefore, using something that implements [`BufRead`], such as
+/// [`BufReader`], will be more efficient.
 ///
 /// # Examples
 ///
-/// [`File`][file]s implement `Read`:
+/// [`File`]s implement `Read`:
 ///
-/// [file]: ../fs/struct.File.html
+/// [`read()`]: trait.Read.html#tymethod.read
+/// [`std::io`]: ../../std/io/index.html
+/// [`File`]: ../fs/struct.File.html
+/// [`BufRead`]: trait.BufRead.html
+/// [`BufReader`]: struct.BufReader.html
 ///
 /// ```
 /// use std::io;
@@ -455,9 +456,9 @@ pub trait Read {
     ///
     /// This function does not provide any guarantees about whether it blocks
     /// waiting for data, but if an object needs to block for a read but cannot
-    /// it will typically signal this via an `Err` return value.
+    /// it will typically signal this via an [`Err`] return value.
     ///
-    /// If the return value of this method is `Ok(n)`, then it must be
+    /// If the return value of this method is [`Ok(n)`], then it must be
     /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates
     /// that the buffer `buf` has been filled in with `n` bytes of data from this
     /// source. If `n` is `0`, then it can indicate one of two scenarios:
@@ -478,14 +479,17 @@ pub trait Read {
     /// variant will be returned. If an error is returned then it must be
     /// guaranteed that no bytes were read.
     ///
-    /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the read
+    /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read
     /// operation should be retried if there is nothing else to do.
     ///
     /// # Examples
     ///
-    /// [`File`][file]s implement `Read`:
+    /// [`File`]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`File`]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -511,18 +515,21 @@ pub trait Read {
     /// buffers.
     ///
     /// If a `Read`er guarantees that it can work properly with uninitialized
-    /// memory, it should call `Initializer::nop()`. See the documentation for
-    /// `Initializer` for details.
+    /// memory, it should call [`Initializer::nop()`]. See the documentation for
+    /// [`Initializer`] for details.
     ///
     /// The behavior of this method must be independent of the state of the
     /// `Read`er - the method only takes `&self` so that it can be used through
     /// trait objects.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This method is unsafe because a `Read`er could otherwise return a
     /// non-zeroing `Initializer` from another `Read` type without an `unsafe`
     /// block.
+    ///
+    /// [`Initializer::nop()`]: ../../std/io/struct.Initializer.html#method.nop
+    /// [`Initializer`]: ../../std/io/struct.Initializer.html
     #[unstable(feature = "read_initializer", issue = "42788")]
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
@@ -532,16 +539,16 @@ pub trait Read {
     /// Read all bytes until EOF in this source, placing them into `buf`.
     ///
     /// All bytes read from this source will be appended to the specified buffer
-    /// `buf`. This function will continuously call `read` to append more data to
-    /// `buf` until `read` returns either `Ok(0)` or an error of
-    /// non-`ErrorKind::Interrupted` kind.
+    /// `buf`. This function will continuously call [`read()`] to append more data to
+    /// `buf` until [`read()`] returns either [`Ok(0)`] or an error of
+    /// non-[`ErrorKind::Interrupted`] kind.
     ///
     /// If successful, this function will return the total number of bytes read.
     ///
     /// # Errors
     ///
     /// If this function encounters an error of the kind
-    /// `ErrorKind::Interrupted` then the error is ignored and the operation
+    /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
     /// will continue.
     ///
     /// If any other read error is encountered then this function immediately
@@ -550,9 +557,12 @@ pub trait Read {
     ///
     /// # Examples
     ///
-    /// [`File`][file]s implement `Read`:
+    /// [`File`]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [`read()`]: trait.Read.html#tymethod.read
+    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`File`]: ../fs/struct.File.html
     ///
     /// ```
     /// use std::io;
@@ -633,11 +643,11 @@ pub trait Read {
     /// # Errors
     ///
     /// If this function encounters an error of the kind
-    /// `ErrorKind::Interrupted` then the error is ignored and the operation
+    /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
     /// will continue.
     ///
     /// If this function encounters an "end of file" before completely filling
-    /// the buffer, it returns an error of the kind `ErrorKind::UnexpectedEof`.
+    /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
     /// The contents of `buf` are unspecified in this case.
     ///
     /// If any other read error is encountered then this function immediately
@@ -649,9 +659,11 @@ pub trait Read {
     ///
     /// # Examples
     ///
-    /// [`File`][file]s implement `Read`:
+    /// [`File`]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [`File`]: ../fs/struct.File.html
+    /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
+    /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
     ///
     /// ```
     /// use std::io;
@@ -722,11 +734,11 @@ pub trait Read {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
 
-    /// Transforms this `Read` instance to an `Iterator` over its bytes.
+    /// Transforms this `Read` instance to an [`Iterator`] over its bytes.
     ///
-    /// The returned type implements `Iterator` where the `Item` is `Result<u8,
-    /// R::Err>`.  The yielded item is `Ok` if a byte was successfully read and
-    /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from
+    /// The returned type implements [`Iterator`] where the `Item` is [`Result`]`<`[`u8`]`,
+    /// R::Err>`. The yielded item is [`Ok`] if a byte was successfully read and
+    /// [`Err`] otherwise for I/O errors. EOF is mapped to returning [`None`] from
     /// this iterator.
     ///
     /// # Examples
@@ -734,6 +746,12 @@ pub trait Read {
     /// [`File`][file]s implement `Read`:
     ///
     /// [file]: ../fs/struct.File.html
+    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
+    /// [`Result`]: ../../std/result/enum.Result.html
+    /// [`u8`]: ../../std/primitive.u8.html
+    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// ```
     /// use std::io;
@@ -754,12 +772,12 @@ pub trait Read {
         Bytes { inner: self }
     }
 
-    /// Transforms this `Read` instance to an `Iterator` over `char`s.
+    /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
     ///
     /// This adaptor will attempt to interpret this reader as a UTF-8 encoded
-    /// sequence of characters. The returned iterator will return `None` once
+    /// sequence of characters. The returned iterator will return [`None`] once
     /// EOF is reached for this reader. Otherwise each element yielded will be a
-    /// `Result<char, E>` where `E` may contain information about what I/O error
+    /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
     /// occurred or where decoding failed.
     ///
     /// Currently this adaptor will discard intermediate data read, and should
@@ -767,9 +785,13 @@ pub trait Read {
     ///
     /// # Examples
     ///
-    /// [`File`][file]s implement `Read`:
+    /// [`File`]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [`File`]: ../fs/struct.File.html
+    /// [`Iterator`]: ../../std/iter/trait.Iterator.html
+    /// [`Result`]: ../../std/result/enum.Result.html
+    /// [`char`]: ../../std/primitive.char.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// ```
     /// #![feature(io)]
@@ -832,15 +854,17 @@ pub trait Read {
     /// Creates an adaptor which will read at most `limit` bytes from it.
     ///
     /// This function returns a new instance of `Read` which will read at most
-    /// `limit` bytes, after which it will always return EOF (`Ok(0)`). Any
+    /// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any
     /// read errors will not count towards the number of bytes read and future
-    /// calls to `read` may succeed.
+    /// calls to [`read()`] may succeed.
     ///
     /// # Examples
     ///
-    /// [`File`][file]s implement `Read`:
+    /// [`File`]s implement `Read`:
     ///
-    /// [file]: ../fs/struct.File.html
+    /// [`File`]: ../fs/struct.File.html
+    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`read()`]: trait.Read.html#tymethod.read
     ///
     /// ```
     /// use std::io;
@@ -879,7 +903,7 @@ impl Initializer {
 
     /// Returns a new `Initializer` which will not zero out buffers.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This may only be called by `Read`ers which guarantee that they will not
     /// read from buffers passed to `Read` methods, and that the return value of
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 880caa2ade5..b57067e35e9 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -81,7 +81,7 @@
 //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
 //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
 //! calls to methods on [`str`] and [`[T]`][slice] respectively, via [deref
-//! coercions].
+//! coercions][deref-coercions].
 //!
 //! Third, the standard library defines [The Rust Prelude], a small collection
 //! of items - mostly traits - that are imported into every module of every
@@ -203,16 +203,13 @@
 //! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use
 //! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules
 //! [crates.io]: https://crates.io
-//! [deref coercions]: ../book/first-edition/deref-coercions.html
+//! [deref-coercions]: ../book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
 //! [files]: fs/struct.File.html
 //! [multithreading]: thread/index.html
 //! [other]: #what-is-in-the-standard-library-documentation
 //! [primitive types]: ../book/first-edition/primitive-types.html
 
-#![crate_name = "std"]
 #![stable(feature = "rust1", since = "1.0.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
@@ -361,6 +358,7 @@ extern crate std_unicode;
 extern crate libc;
 
 // We always need an unwinder currently for backtraces
+#[allow(unused_extern_crates)]
 extern crate unwind;
 
 // compiler-rt intrinsics
diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs
index 98642f86f4d..240e82069ff 100644
--- a/src/libstd/memchr.rs
+++ b/src/libstd/memchr.rs
@@ -20,7 +20,7 @@
 /// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
 /// (See benchmarks.)
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the first position of a byte in a byte string.
 ///
@@ -40,7 +40,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// Returns the index corresponding to the last occurrence of `needle` in
 /// `haystack`, or `None` if one is not found.
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the last position of a byte in a byte string.
 ///
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 99567bd08bb..739dc4163fe 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -453,7 +453,7 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
     let mut any_data = 0;
     let mut any_vtable = 0;
     let mut data = Data {
-        f: f,
+        f,
     };
 
     let r = __rust_maybe_catch_panic(do_call::<F, R>,
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index c90a0c78527..830b9dc475d 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -323,6 +323,11 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
     mem::transmute(s)
 }
 
+// Detect scheme on Redox
+fn has_redox_scheme(s: &[u8]) -> bool {
+    cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':')
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Cross-platform, iterator-independent parsing
 ////////////////////////////////////////////////////////////////////////////////
@@ -1685,8 +1690,12 @@ impl Path {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
-        // FIXME: Remove target_os = "redox" and allow Redox prefixes
-        self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some())
+        if !cfg!(target_os = "redox") {
+            self.has_root() && (cfg!(unix) || self.prefix().is_some())
+        } else {
+            // FIXME: Allow Redox prefixes
+            has_redox_scheme(self.as_u8_slice())
+        }
     }
 
     /// Returns `true` if the `Path` is relative, i.e. not absolute.
@@ -2049,8 +2058,9 @@ impl Path {
         let prefix = parse_prefix(self.as_os_str());
         Components {
             path: self.as_u8_slice(),
-            prefix: prefix,
-            has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
+            prefix,
+            has_physical_root: has_physical_root(self.as_u8_slice(), prefix) ||
+                               has_redox_scheme(self.as_u8_slice()),
             front: State::Prefix,
             back: State::Body,
         }
@@ -3953,4 +3963,10 @@ mod tests {
         assert_eq!(path, path_buf);
         assert!(path_buf.into_os_string().capacity() >= 15);
     }
+
+    #[test]
+    fn display_format_flags() {
+        assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b");
+        assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b");
+    }
 }
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index 49cdba21a1d..538753d8692 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -23,6 +23,7 @@
 //! On a technical level, Rust inserts
 //!
 //! ```
+//! # #[allow(unused_extern_crates)]
 //! extern crate std;
 //! ```
 //!
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index c52899db437..76ef36cc9a7 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -103,26 +103,31 @@ mod prim_bool { }
 /// [`String`]: string/struct.String.html
 ///
 /// As always, remember that a human intuition for 'character' may not map to
-/// Unicode's definitions. For example, emoji symbols such as '❤️' can be more
-/// than one Unicode code point; this ❤️ in particular is two:
+/// Unicode's definitions. For example, despite looking similar, the 'é'
+/// character is one Unicode code point while 'é' is two Unicode code points:
 ///
 /// ```
-/// let s = String::from("❤️");
+/// let mut chars = "é".chars();
+/// // U+00e9: 'latin small letter e with acute'
+/// assert_eq!(Some('\u{00e9}'), chars.next());
+/// assert_eq!(None, chars.next());
 ///
-/// // we get two chars out of a single ❤️
-/// let mut iter = s.chars();
-/// assert_eq!(Some('\u{2764}'), iter.next());
-/// assert_eq!(Some('\u{fe0f}'), iter.next());
-/// assert_eq!(None, iter.next());
+/// let mut chars = "é".chars();
+/// // U+0065: 'latin small letter e'
+/// assert_eq!(Some('\u{0065}'), chars.next());
+/// // U+0301: 'combining acute accent'
+/// assert_eq!(Some('\u{0301}'), chars.next());
+/// assert_eq!(None, chars.next());
 /// ```
 ///
-/// This means it won't fit into a `char`. Trying to create a literal with
-/// `let heart = '❤️';` gives an error:
+/// This means that the contents of the first string above _will_ fit into a
+/// `char` while the contents of the second string _will not_. Trying to create
+/// a `char` literal with the contents of the second string gives an error:
 ///
 /// ```text
-/// error: character literal may only contain one codepoint: '❤
-/// let heart = '❤️';
-///             ^~
+/// error: character literal may only contain one codepoint: 'é'
+/// let c = 'é';
+///         ^^^^
 /// ```
 ///
 /// Another implication of the 4-byte fixed size of a `char` is that
@@ -183,9 +188,10 @@ mod prim_unit { }
 /// Working with raw pointers in Rust is uncommon,
 /// typically limited to a few patterns.
 ///
-/// Use the [`null`] function to create null pointers, and the [`is_null`] method
-/// of the `*const T` type  to check for null. The `*const T` type also defines
-/// the [`offset`] method, for pointer math.
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
 ///
 /// # Common ways to create raw pointers
 ///
@@ -256,6 +262,7 @@ mod prim_unit { }
 /// *[See also the `std::ptr` module](ptr/index.html).*
 ///
 /// [`null`]: ../std/ptr/fn.null.html
+/// [`null_mut`]: ../std/ptr/fn.null_mut.html
 /// [`is_null`]: ../std/primitive.pointer.html#method.is_null
 /// [`offset`]: ../std/primitive.pointer.html#method.offset
 /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index a872e7eee06..a3a7e91dd80 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -126,7 +126,7 @@ impl AsInner<imp::Process> for Child {
 impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
     fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
         Child {
-            handle: handle,
+            handle,
             stdin: io.stdin.map(ChildStdin::from_inner),
             stdout: io.stdout.map(ChildStdout::from_inner),
             stderr: io.stderr.map(ChildStderr::from_inner),
@@ -1035,9 +1035,9 @@ impl Child {
 
         let status = self.wait()?;
         Ok(Output {
-            status: status,
-            stdout: stdout,
-            stderr: stderr,
+            status,
+            stdout,
+            stderr,
         })
     }
 }
diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs
index 0f9ef6fabb0..c08bd6d133d 100644
--- a/src/libstd/sync/mpsc/blocking.rs
+++ b/src/libstd/sync/mpsc/blocking.rs
@@ -46,7 +46,7 @@ pub fn tokens() -> (WaitToken, SignalToken) {
         inner: inner.clone(),
     };
     let signal_token = SignalToken {
-        inner: inner
+        inner,
     };
     (wait_token, signal_token)
 }
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 8b4da532af6..e49f4cff024 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -148,12 +148,12 @@ impl Select {
         let id = self.next_id.get();
         self.next_id.set(id + 1);
         Handle {
-            id: id,
+            id,
             selector: self.inner.get(),
             next: ptr::null_mut(),
             prev: ptr::null_mut(),
             added: false,
-            rx: rx,
+            rx,
             packet: rx,
         }
     }
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 1d16e002a2b..90f12c826d6 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -177,7 +177,7 @@ impl<T> Packet<T> {
             lock: Mutex::new(State {
                 disconnected: false,
                 blocker: NoneBlocked,
-                cap: cap,
+                cap,
                 canceled: None,
                 queue: Queue {
                     head: ptr::null_mut(),
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index bb18fe95a9d..403685a4b8e 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -387,7 +387,7 @@ impl Drop for Finish {
 impl OnceState {
     /// Returns whether the associated [`Once`] has been poisoned.
     ///
-    /// Once an initalization routine for a [`Once`] has panicked it will forever
+    /// Once an initialization routine for a [`Once`] has panicked it will forever
     /// indicate to future forced initialization routines that it is poisoned.
     ///
     /// [`Once`]: struct.Once.html
diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs
index 6e44ad705fe..59ae2a74a6d 100644
--- a/src/libstd/sys/redox/args.rs
+++ b/src/libstd/sys/redox/args.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Global initialization and retreival of command line arguments.
+//! Global initialization and retrieval of command line arguments.
 //!
 //! On some platforms these are stored during runtime startup,
 //! and on some they are retrieved from the system on demand.
diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs
deleted file mode 100644
index 6cafe3e69ba..00000000000
--- a/src/libstd/sys/redox/backtrace.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use io;
-use sys_common::backtrace::Frame;
-
-pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
-pub struct BacktraceContext;
-
-#[inline(never)]
-pub fn unwind_backtrace(_frames: &mut [Frame])
-    -> io::Result<(usize, BacktraceContext)>
-{
-    Ok((0, BacktraceContext))
-}
-
-pub mod gnu {
-    use io;
-    use fs;
-    use libc::c_char;
-
-    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
-        Err(io::Error::new(io::ErrorKind::Other, "Not implemented"))
-    }
-}
diff --git a/src/libstd/sys/redox/backtrace/mod.rs b/src/libstd/sys/redox/backtrace/mod.rs
new file mode 100644
index 00000000000..40b957d847b
--- /dev/null
+++ b/src/libstd/sys/redox/backtrace/mod.rs
@@ -0,0 +1,42 @@
+// 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.
+
+/// See sys/unix/backtrace/mod.rs for an explanation of the method used here.
+
+pub use self::tracing::unwind_backtrace;
+pub use self::printing::{foreach_symbol_fileline, resolve_symname};
+
+// tracing impls:
+mod tracing;
+// symbol resolvers:
+mod printing;
+
+pub mod gnu {
+    use io;
+    use fs;
+    use libc::c_char;
+    use vec::Vec;
+    use ffi::OsStr;
+    use os::unix::ffi::OsStrExt;
+    use io::Read;
+
+    pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
+        let mut exefile = fs::File::open("sys:exe")?;
+        let mut exename = Vec::new();
+        exefile.read_to_end(&mut exename)?;
+        if exename.last() == Some(&b'\n') {
+            exename.pop();
+        }
+        let file = fs::File::open(OsStr::from_bytes(&exename))?;
+        Ok((exename.into_iter().map(|c| c as c_char).collect(), file))
+    }
+}
+
+pub struct BacktraceContext;
diff --git a/src/libstd/sys/redox/backtrace/printing.rs b/src/libstd/sys/redox/backtrace/printing.rs
new file mode 100644
index 00000000000..3e937dbe623
--- /dev/null
+++ b/src/libstd/sys/redox/backtrace/printing.rs
@@ -0,0 +1,11 @@
+// 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.
+
+pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs
new file mode 100644
index 00000000000..cfeabaddda9
--- /dev/null
+++ b/src/libstd/sys/redox/backtrace/tracing.rs
@@ -0,0 +1,106 @@
+// 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.
+
+use error::Error;
+use io;
+use libc;
+use sys::backtrace::BacktraceContext;
+use sys_common::backtrace::Frame;
+
+use unwind as uw;
+
+struct Context<'a> {
+    idx: usize,
+    frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+    fn description(&self) -> &'static str {
+        "unexpected return value while unwinding"
+    }
+}
+
+impl ::fmt::Display for UnwindError {
+    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+        write!(f, "{}: {:?}", self.description(), self.0)
+    }
+}
+
+#[inline(never)] // if we know this is a function call, we can skip it when
+                 // tracing
+pub fn unwind_backtrace(frames: &mut [Frame])
+    -> io::Result<(usize, BacktraceContext)>
+{
+    let mut cx = Context {
+        idx: 0,
+        frames: frames,
+    };
+    let result_unwind = unsafe {
+        uw::_Unwind_Backtrace(trace_fn,
+                              &mut cx as *mut Context
+                              as *mut libc::c_void)
+    };
+    // See libunwind:src/unwind/Backtrace.c for the return values.
+    // No, there is no doc.
+    match result_unwind {
+        // These return codes seem to be benign and need to be ignored for backtraces
+        // to show up properly on all tested platforms.
+        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+            Ok((cx.idx, BacktraceContext))
+        }
+        _ => {
+            Err(io::Error::new(io::ErrorKind::Other,
+                               UnwindError(result_unwind)))
+        }
+    }
+}
+
+extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
+                   arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
+    let cx = unsafe { &mut *(arg as *mut Context) };
+    let mut ip_before_insn = 0;
+    let mut ip = unsafe {
+        uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void
+    };
+    if !ip.is_null() && ip_before_insn == 0 {
+        // this is a non-signaling frame, so `ip` refers to the address
+        // after the calling instruction. account for that.
+        ip = (ip as usize - 1) as *mut _;
+    }
+
+    // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
+    // it appears to work fine without it, so we only use
+    // FindEnclosingFunction on non-osx platforms. In doing so, we get a
+    // slightly more accurate stack trace in the process.
+    //
+    // This is often because panic involves the last instruction of a
+    // function being "call std::rt::begin_unwind", with no ret
+    // instructions after it. This means that the return instruction
+    // pointer points *outside* of the calling function, and by
+    // unwinding it we go back to the original function.
+    let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
+        ip
+    } else {
+        unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
+    };
+
+    if cx.idx < cx.frames.len() {
+        cx.frames[cx.idx] = Frame {
+            symbol_addr: symaddr,
+            exact_position: ip,
+        };
+        cx.idx += 1;
+    }
+
+    uw::_URC_NO_REASON
+}
diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs
index 259cda5bcb3..9fd8d6c9186 100644
--- a/src/libstd/sys/redox/ext/mod.rs
+++ b/src/libstd/sys/redox/ext/mod.rs
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs
index 49cde89dc05..1a26257e4a7 100644
--- a/src/libstd/sys/redox/net/dns/mod.rs
+++ b/src/libstd/sys/redox/net/dns/mod.rs
@@ -206,10 +206,10 @@ impl Dns {
         }
 
         Ok(Dns {
-            transaction_id: transaction_id,
-            flags: flags,
-            queries: queries,
-            answers: answers,
+            transaction_id,
+            flags,
+            queries,
+            answers,
         })
     }
 }
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
index 17fa07b99ae..d87364b8121 100644
--- a/src/libstd/sys/redox/process.rs
+++ b/src/libstd/sys/redox/process.rs
@@ -336,7 +336,7 @@ impl Command {
                 panic!("return from exec without err");
             }
         } else {
-            io::Error::new(io::ErrorKind::NotFound, "")
+            io::Error::from_raw_os_error(syscall::ENOENT)
         }
     }
 
diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs
index bbdcb5d3616..810d2d40c05 100644
--- a/src/libstd/sys/unix/args.rs
+++ b/src/libstd/sys/unix/args.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Global initialization and retreival of command line arguments.
+//! Global initialization and retrieval of command line arguments.
 //!
 //! On some platforms these are stored during runtime startup,
 //! and on some they are retrieved from the system on demand.
diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
index cfeabaddda9..e3ffbe88acd 100644
--- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
+++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs
@@ -43,7 +43,7 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 {
     let mut cx = Context {
         idx: 0,
-        frames: frames,
+        frames,
     };
     let result_unwind = unsafe {
         uw::_Unwind_Backtrace(trace_fn,
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index a94585723a1..f44b9aa9615 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -154,8 +154,6 @@ pub trait OpenOptionsExt {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(libc)]
-    /// extern crate libc;
     /// use std::fs::OpenOptions;
     /// use std::os::unix::fs::OpenOptionsExt;
     ///
diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs
index a0323d933d6..c9fe3590a64 100644
--- a/src/libstd/sys/unix/ext/io.rs
+++ b/src/libstd/sys/unix/ext/io.rs
@@ -13,11 +13,10 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use fs;
-use net;
 use os::raw;
 use sys;
 use io;
-use sys_common::{self, AsInner, FromInner, IntoInner};
+use sys_common::{AsInner, FromInner, IntoInner};
 use libc;
 
 /// Raw file descriptors.
@@ -93,19 +92,6 @@ impl IntoRawFd for fs::File {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpStream {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpListener {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::UdpSocket {
-    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-}
-
 #[stable(feature = "asraw_stdio", since = "1.21.0")]
 impl AsRawFd for io::Stdin {
     fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO }
@@ -120,44 +106,3 @@ impl AsRawFd for io::Stdout {
 impl AsRawFd for io::Stderr {
     fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO }
 }
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
-    }
-}
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
-    }
-}
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::UdpSocket {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
-    }
-}
-
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::UdpSocket {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index 67fe46cc9c7..98bc90dd4e1 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 27853427128..86b0f35be92 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -30,14 +30,14 @@ use ffi::OsStr;
 use fmt;
 use io::{self, Initializer};
 use mem;
-use net::Shutdown;
+use net::{self, Shutdown};
 use os::unix::ffi::OsStrExt;
 use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
 use path::Path;
 use time::Duration;
-use sys::cvt;
+use sys::{self, cvt};
 use sys::net::Socket;
-use sys_common::{AsInner, FromInner, IntoInner};
+use sys_common::{self, AsInner, FromInner, IntoInner};
 
 #[cfg(any(target_os = "linux", target_os = "android",
           target_os = "dragonfly", target_os = "freebsd",
@@ -141,8 +141,8 @@ impl SocketAddr {
         }
 
         Ok(SocketAddr {
-            addr: addr,
-            len: len,
+            addr,
+            len,
         })
     }
 
@@ -588,6 +588,64 @@ impl IntoRawFd for UnixStream {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_socket().into_inner()
+    }
+}
+
 /// A structure representing a Unix domain socket server.
 ///
 /// # Examples
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 4e6fde5c29d..cb0f687e072 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -170,11 +170,17 @@ impl AsInner<stat64> for FileAttr {
 }
 
 impl FilePermissions {
-    pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
+    pub fn readonly(&self) -> bool {
+        // check if any class (owner, group, others) has write permission
+        self.mode & 0o222 == 0
+    }
+
     pub fn set_readonly(&mut self, readonly: bool) {
         if readonly {
+            // remove write permission for all classes; equivalent to `chmod a-w <file>`
             self.mode &= !0o222;
         } else {
+            // add write permission for all classes; equivalent to `chmod a+w <file>`
             self.mode |= 0o222;
         }
     }
diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs
index ab609126cdb..bc20a74f114 100644
--- a/src/libstd/sys/unix/process/magenta.rs
+++ b/src/libstd/sys/unix/process/magenta.rs
@@ -61,7 +61,7 @@ pub struct Handle {
 impl Handle {
     pub fn new(raw: mx_handle_t) -> Handle {
         Handle {
-            raw: raw,
+            raw,
         }
     }
 
diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs
index 839e2d88d6a..689ccd78524 100644
--- a/src/libstd/sys/unix/process/process_common.rs
+++ b/src/libstd/sys/unix/process/process_common.rs
@@ -94,14 +94,14 @@ impl Command {
         let program = os2c(program, &mut saw_nul);
         Command {
             argv: vec![program.as_ptr(), ptr::null()],
-            program: program,
+            program,
             args: Vec::new(),
             env: None,
             envp: None,
             cwd: None,
             uid: None,
             gid: None,
-            saw_nul: saw_nul,
+            saw_nul,
             closures: Vec::new(),
             stdin: None,
             stdout: None,
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 15747746611..40f1d6a6db1 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -168,7 +168,8 @@ impl Thread {
         unsafe {
             let ret = libc::pthread_join(self.id, ptr::null_mut());
             mem::forget(self);
-            debug_assert_eq!(ret, 0);
+            assert!(ret == 0,
+                    "failed to join thread: {}", io::Error::from_raw_os_error(ret));
         }
     }
 
diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs
index 99ab8741159..18944be58ee 100644
--- a/src/libstd/sys/unix/weak.rs
+++ b/src/libstd/sys/unix/weak.rs
@@ -49,7 +49,7 @@ pub struct Weak<F> {
 impl<F> Weak<F> {
     pub const fn new(name: &'static str) -> Weak<F> {
         Weak {
-            name: name,
+            name,
             addr: AtomicUsize::new(1),
             _marker: marker::PhantomData,
         }
diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs
index 3c3fd8d3e4a..26b4cb90e0a 100644
--- a/src/libstd/sys/windows/backtrace/mod.rs
+++ b/src/libstd/sys/windows/backtrace/mod.rs
@@ -68,8 +68,8 @@ pub fn unwind_backtrace(frames: &mut [Frame])
 
     let backtrace_context = BacktraceContext {
         handle: process,
-        SymCleanup: SymCleanup,
-        dbghelp: dbghelp,
+        SymCleanup,
+        dbghelp,
     };
 
     // Initialize this process's symbols
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index ba54ca6ea18..7dfcc996e18 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -273,6 +273,7 @@ pub const FILE_END: DWORD = 2;
 
 pub const WAIT_OBJECT_0: DWORD = 0x00000000;
 pub const WAIT_TIMEOUT: DWORD = 258;
+pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
 
 #[cfg(target_env = "msvc")]
 pub const MAX_SYM_NAME: usize = 2000;
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index be7482c4bb1..452d720ce59 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -239,10 +239,10 @@ impl<'a> AsyncPipe<'a> {
         };
         overlapped.hEvent = event.raw();
         Ok(AsyncPipe {
-            pipe: pipe,
-            overlapped: overlapped,
-            event: event,
-            dst: dst,
+            pipe,
+            overlapped,
+            event,
+            dst,
             state: State::NotReading,
         })
     }
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 5a376a867ee..2cdd86e88b0 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -61,7 +61,11 @@ impl Thread {
     }
 
     pub fn join(self) {
-        unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE); }
+        let rc = unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE) };
+        if rc == c::WAIT_FAILED {
+            panic!("failed to join on thread: {}",
+                   io::Error::last_os_error());
+        }
     }
 
     pub fn yield_now() {
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index ad57f87dc1f..7ae9ed917bd 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -122,8 +122,8 @@ struct Node {
 
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
     let mut node = Box::new(Node {
-        key: key,
-        dtor: dtor,
+        key,
+        dtor,
         next: ptr::null_mut(),
     });
 
diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs
index 2abb8afa828..7970042b1d6 100644
--- a/src/libstd/sys_common/thread_info.rs
+++ b/src/libstd/sys_common/thread_info.rs
@@ -45,7 +45,7 @@ pub fn stack_guard() -> Option<usize> {
 pub fn set(stack_guard: Option<usize>, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
-        stack_guard: stack_guard,
-        thread: thread,
+        stack_guard,
+        thread,
     }));
 }
diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs
index 1f889c70707..87ffd304e1a 100644
--- a/src/libstd/sys_common/thread_local.rs
+++ b/src/libstd/sys_common/thread_local.rs
@@ -128,7 +128,7 @@ impl StaticKey {
     pub const fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> StaticKey {
         StaticKey {
             key: atomic::AtomicUsize::new(0),
-            dtor: dtor
+            dtor,
         }
     }
 
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index 4e4a6e77d12..b89a73cd28a 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -452,10 +452,14 @@ impl fmt::Display for Wtf8 {
                     pos = surrogate_pos + 3;
                 },
                 None => {
-                    formatter.write_str(unsafe {
+                    let s = unsafe {
                         str::from_utf8_unchecked(&wtf8_bytes[pos..])
-                    })?;
-                    return Ok(());
+                    };
+                    if pos == 0 {
+                        return s.fmt(formatter)
+                    } else {
+                        return formatter.write_str(s)
+                    }
                 }
             }
         }
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index 48f611a3439..7a9b642350f 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -258,8 +258,8 @@ impl<T: 'static> LocalKey<T> {
     pub const unsafe fn new(inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>,
                             init: fn() -> T) -> LocalKey<T> {
         LocalKey {
-            inner: inner,
-            init: init,
+            inner,
+            init,
         }
     }
 
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 3cd9cf7727c..4912ff93abd 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -374,7 +374,7 @@ impl Builder {
     {
         let Builder { name, stack_size } = self;
 
-        let stack_size = stack_size.unwrap_or(util::min_stack());
+        let stack_size = stack_size.unwrap_or_else(util::min_stack);
 
         let my_thread = Thread::new(name);
         let their_thread = my_thread.clone();
@@ -560,7 +560,7 @@ pub fn current() -> Thread {
 /// implementing low-level shared resources or synchronization primitives.
 ///
 /// However programmers will usually prefer to use, [`channel`]s, [`Condvar`]s,
-/// [`Mutex`]es or [`join`] for their synchronisation routines, as they avoid
+/// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid
 /// thinking about thread scheduling.
 ///
 /// Note that [`channel`]s for example are implemented using this primitive.
@@ -807,7 +807,7 @@ pub fn park_timeout_ms(ms: u32) {
 /// Platforms which do not support nanosecond precision for sleeping will have
 /// `dur` rounded up to the nearest granularity of time they can sleep for.
 ///
-/// # Example
+/// # Examples
 ///
 /// Waiting for the complete expiration of the timeout:
 ///
@@ -1230,6 +1230,11 @@ impl<T> JoinHandle<T> {
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`panic`]: ../../std/macro.panic.html
     ///
+    /// # Panics
+    ///
+    /// This function may panic on some platforms if a thread attempts to join
+    /// itself or otherwise may create a deadlock with joining threads.
+    ///
     /// # Examples
     ///
     /// ```
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 48819adb23e..d715a0d740b 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -197,8 +197,8 @@ impl Duration {
             }
             debug_assert!(nanos < NANOS_PER_SEC);
             Some(Duration {
-                secs: secs,
-                nanos: nanos,
+                secs,
+                nanos,
             })
         } else {
             None
@@ -268,8 +268,8 @@ impl Duration {
             .and_then(|s| s.checked_add(extra_secs)) {
             debug_assert!(nanos < NANOS_PER_SEC);
             Some(Duration {
-                secs: secs,
-                nanos: nanos,
+                secs,
+                nanos,
             })
         } else {
             None
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
index e8eb4abaa40..5b893505b34 100644
--- a/src/libstd/time/mod.rs
+++ b/src/libstd/time/mod.rs
@@ -112,7 +112,7 @@ pub struct Instant(time::Instant);
 ///            println!("{}", elapsed.as_secs());
 ///        }
 ///        Err(e) => {
-///            // an error occured!
+///            // an error occurred!
 ///            println!("Error: {:?}", e);
 ///        }
 ///    }
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index 698210e83f3..e5a114caed0 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -20,9 +20,7 @@
 //! provide for basic string-related manipulations. This crate does not
 //! (yet) aim to provide a full set of Unicode tables.
 
-#![crate_name = "std_unicode"]
 #![unstable(feature = "unicode", issue = "27783")]
-#![crate_type = "rlib"]
 #![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/",
@@ -34,7 +32,6 @@
 
 #![feature(core_char_ext)]
 #![feature(str_internals)]
-#![feature(core_intrinsics)]
 #![feature(decode_utf8)]
 #![feature(fused)]
 #![feature(fn_traits)]
diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs
index b914cbcf4b8..253dcb6a159 100644
--- a/src/libstd_unicode/lossy.rs
+++ b/src/libstd_unicode/lossy.rs
@@ -12,7 +12,7 @@ use core::str as core_str;
 use core::fmt;
 use core::fmt::Write;
 use char;
-use core::intrinsics;
+use core::mem;
 
 
 /// Lossy UTF-8 string.
@@ -27,7 +27,7 @@ impl Utf8Lossy {
     }
 
     pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
-        unsafe { intrinsics::transmute(bytes) }
+        unsafe { mem::transmute(bytes) }
     }
 
     pub fn chunks(&self) -> Utf8LossyChunksIter {
@@ -153,7 +153,21 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
 
 impl fmt::Display for Utf8Lossy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // If we're the empty string then our iterator won't actually yield
+        // anything, so perform the formatting manually
+        if self.bytes.len() == 0 {
+            return "".fmt(f)
+        }
+
         for Utf8LossyChunk { valid, broken } in self.chunks() {
+            // If we successfully decoded the whole chunk as a valid string then
+            // we can return a direct formatting of the string which will also
+            // respect various formatting flags if possible.
+            if valid.len() == self.bytes.len() {
+                assert!(broken.is_empty());
+                return valid.fmt(f)
+            }
+
             f.write_str(valid)?;
             if !broken.is_empty() {
                 f.write_char(char::REPLACEMENT_CHARACTER)?;
diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs
index 54a5288a57c..1274b062587 100644
--- a/src/libstd_unicode/u_str.rs
+++ b/src/libstd_unicode/u_str.rs
@@ -87,7 +87,7 @@ impl<I> Utf16Encoder<I> {
         where I: Iterator<Item = char>
     {
         Utf16Encoder {
-            chars: chars,
+            chars,
             extra: 0,
         }
     }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 38ef79822c7..fa4df2196a3 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -135,7 +135,7 @@ impl PathSegment {
     pub fn crate_root(span: Span) -> Self {
         PathSegment {
             identifier: Ident { ctxt: span.ctxt, ..keywords::CrateRoot.ident() },
-            span: span,
+            span,
             parameters: None,
         }
     }
@@ -844,6 +844,32 @@ pub struct Expr {
     pub attrs: ThinVec<Attribute>
 }
 
+impl Expr {
+    /// Wether this expression would be valid somewhere that expects a value, for example, an `if`
+    /// condition.
+    pub fn returns(&self) -> bool {
+        if let ExprKind::Block(ref block) = self.node {
+            match block.stmts.last().map(|last_stmt| &last_stmt.node) {
+                // implicit return
+                Some(&StmtKind::Expr(_)) => true,
+                Some(&StmtKind::Semi(ref expr)) => {
+                    if let ExprKind::Ret(_) = expr.node {
+                        // last statement is explicit return
+                        true
+                    } else {
+                        false
+                    }
+                }
+                // This is a block that doesn't end in either an implicit or explicit return
+                _ => false,
+            }
+        } else {
+            // This is not a block, it is a value
+            true
+        }
+    }
+}
+
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self))
@@ -1492,15 +1518,15 @@ impl Arg {
         let infer_ty = P(Ty {
             id: DUMMY_NODE_ID,
             node: TyKind::ImplicitSelf,
-            span: span,
+            span,
         });
         let arg = |mutbl, ty| Arg {
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
                 node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
-                span: span,
+                span,
             }),
-            ty: ty,
+            ty,
             id: DUMMY_NODE_ID,
         };
         match eself.node {
@@ -1509,7 +1535,7 @@ impl Arg {
             SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty {
                 id: DUMMY_NODE_ID,
                 node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }),
-                span: span,
+                span,
             })),
         }
     }
@@ -1738,7 +1764,7 @@ impl PolyTraitRef {
         PolyTraitRef {
             bound_lifetimes: lifetimes,
             trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID },
-            span: span,
+            span,
         }
     }
 }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index d5caf458fd7..ca87c807103 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -438,7 +438,7 @@ pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute {
 /// Returns an inner attribute with the given value and span.
 pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute {
     Attribute {
-        id: id,
+        id,
         style: ast::AttrStyle::Inner,
         path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
         tokens: item.node.tokens(item.span),
@@ -456,7 +456,7 @@ pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute {
 /// Returns an outer attribute with the given value and span.
 pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute {
     Attribute {
-        id: id,
+        id,
         style: ast::AttrStyle::Outer,
         path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)),
         tokens: item.node.tokens(item.span),
@@ -469,12 +469,12 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute {
     let style = doc_comment_style(&text.as_str());
     let lit = respan(span, LitKind::Str(text, ast::StrStyle::Cooked));
     Attribute {
-        id: id,
-        style: style,
+        id,
+        style,
         path: ast::Path::from_ident(span, ast::Ident::from_str("doc")),
         tokens: MetaItemKind::NameValue(lit).tokens(span),
         is_sugared_doc: true,
-        span: span,
+        span,
     }
 }
 
@@ -718,8 +718,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     match (since, reason) {
                         (Some(since), Some(reason)) => {
                             rustc_depr = Some(RustcDeprecation {
-                                since: since,
-                                reason: reason,
+                                since,
+                                reason,
                             })
                         }
                         (None, _) => {
@@ -763,7 +763,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                         (Some(feature), reason, Some(issue)) => {
                             stab = Some(Stability {
                                 level: Unstable {
-                                    reason: reason,
+                                    reason,
                                     issue: {
                                         if let Ok(issue) = issue.as_str().parse() {
                                             issue
@@ -774,7 +774,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                         }
                                     }
                                 },
-                                feature: feature,
+                                feature,
                                 rustc_depr: None,
                             })
                         }
@@ -817,9 +817,9 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                         (Some(feature), Some(since)) => {
                             stab = Some(Stability {
                                 level: Stable {
-                                    since: since,
+                                    since,
                                 },
-                                feature: feature,
+                                feature,
                                 rustc_depr: None,
                             })
                         }
@@ -1064,26 +1064,21 @@ impl MetaItem {
             },
             _ => return None,
         };
+        let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi);
         let node = match MetaItemKind::from_tokens(tokens) {
             Some(node) => node,
             _ => return None,
         };
-        if let Some(last_span) = node.last_span() {
-            span.hi = last_span.hi;
-        }
+        span.hi = match node {
+            MetaItemKind::NameValue(ref lit) => lit.span.hi,
+            MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi),
+            _ => span.hi,
+        };
         Some(MetaItem { name: name, span: span, node: node })
     }
 }
 
 impl MetaItemKind {
-    fn last_span(&self) -> Option<Span> {
-        match *self {
-            MetaItemKind::Word => None,
-            MetaItemKind::List(ref list) => list.last().map(NestedMetaItem::span),
-            MetaItemKind::NameValue(ref lit) => Some(lit.span),
-        }
-    }
-
     pub fn tokens(&self, span: Span) -> TokenStream {
         match *self {
             MetaItemKind::Word => TokenStream::empty(),
@@ -1130,7 +1125,7 @@ impl MetaItemKind {
         let mut result = Vec::new();
         while let Some(..) = tokens.peek() {
             match NestedMetaItemKind::from_tokens(&mut tokens) {
-                Some(item) => result.push(Spanned { span: item.span(), node: item }),
+                Some(item) => result.push(respan(item.span(), item)),
                 None => return None,
             }
             match tokens.next() {
@@ -1163,7 +1158,7 @@ impl NestedMetaItemKind {
         if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() {
             if let Some(node) = LitKind::from_token(token) {
                 tokens.next();
-                return Some(NestedMetaItemKind::Literal(Spanned { node: node, span: span }));
+                return Some(NestedMetaItemKind::Literal(respan(span, node)));
             }
         }
 
@@ -1256,7 +1251,7 @@ pub trait HasAttrs: Sized {
 impl<T: HasAttrs> HasAttrs for Spanned<T> {
     fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() }
     fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self {
-        Spanned { node: self.node.map_attrs(f), span: self.span }
+        respan(self.span, self.node.map_attrs(f))
     }
 }
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 6c48b4cadd8..30ae7df9353 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -115,7 +115,7 @@ impl CodeMap {
         CodeMap {
             files: RefCell::new(Vec::new()),
             file_loader: Box::new(RealFileLoader),
-            path_mapping: path_mapping,
+            path_mapping,
         }
     }
 
@@ -124,8 +124,8 @@ impl CodeMap {
                             -> CodeMap {
         CodeMap {
             files: RefCell::new(Vec::new()),
-            file_loader: file_loader,
-            path_mapping: path_mapping,
+            file_loader,
+            path_mapping,
         }
     }
 
@@ -215,13 +215,13 @@ impl CodeMap {
 
         let filemap = Rc::new(FileMap {
             name: filename,
-            name_was_remapped: name_was_remapped,
-            crate_of_origin: crate_of_origin,
+            name_was_remapped,
+            crate_of_origin,
             src: None,
-            src_hash: src_hash,
+            src_hash,
             external_src: RefCell::new(ExternalSource::AbsentOk),
-            start_pos: start_pos,
-            end_pos: end_pos,
+            start_pos,
+            end_pos,
             lines: RefCell::new(file_local_lines),
             multibyte_chars: RefCell::new(file_local_multibyte_chars),
         });
@@ -255,7 +255,7 @@ impl CodeMap {
                 assert!(chpos >= linechpos);
                 Loc {
                     file: f,
-                    line: line,
+                    line,
                     col: chpos - linechpos,
                 }
             }
@@ -385,15 +385,15 @@ impl CodeMap {
             let line_len = lo.file.get_line(line_index)
                                   .map(|s| s.chars().count())
                                   .unwrap_or(0);
-            lines.push(LineInfo { line_index: line_index,
-                                  start_col: start_col,
+            lines.push(LineInfo { line_index,
+                                  start_col,
                                   end_col: CharPos::from_usize(line_len) });
             start_col = CharPos::from_usize(0);
         }
 
         // For the last line, it extends from `start_col` to `hi.col`:
         lines.push(LineInfo { line_index: hi.line - 1,
-                              start_col: start_col,
+                              start_col,
                               end_col: hi.col });
 
         Ok(FileLines {file: lo.file, lines: lines})
@@ -426,7 +426,7 @@ impl CodeMap {
                 return Err(SpanSnippetError::MalformedForCodemap(
                     MalformedCodemapPositions {
                         name: local_begin.fm.name.clone(),
-                        source_len: source_len,
+                        source_len,
                         begin_pos: local_begin.pos,
                         end_pos: local_end.pos,
                     }));
@@ -581,7 +581,7 @@ impl FilePathMapping {
 
     pub fn new(mapping: Vec<(String, String)>) -> FilePathMapping {
         FilePathMapping {
-            mapping: mapping
+            mapping,
         }
     }
 
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 54e6dde41e6..14f1f8fbf8c 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -32,8 +32,8 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool)
     let features;
     {
         let mut strip_unconfigured = StripUnconfigured {
-            should_test: should_test,
-            sess: sess,
+            should_test,
+            sess,
             features: None,
         };
 
@@ -105,10 +105,10 @@ impl<'a> StripUnconfigured<'a> {
             self.process_cfg_attr(ast::Attribute {
                 id: attr::mk_attr_id(),
                 style: attr.style,
-                path: path,
-                tokens: tokens,
+                path,
+                tokens,
                 is_sugared_doc: false,
-                span: span,
+                span,
             })
         } else {
             None
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 855f4cd3557..5224f52c496 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -133,7 +133,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
     // Add the error to the map.
     with_registered_diagnostics(|diagnostics| {
         let info = ErrorInfo {
-            description: description,
+            description,
             use_site: None
         };
         if diagnostics.insert(code.name, info).is_some() {
@@ -235,7 +235,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                 expr,
             ),
             vis: ast::Visibility::Public,
-            span: span,
+            span,
             tokens: None,
         })
     ]))
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 72b2552f64f..e57d9c6fe89 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -677,10 +677,10 @@ impl<'a> ExtCtxt<'a> {
                resolver: &'a mut Resolver)
                -> ExtCtxt<'a> {
         ExtCtxt {
-            parse_sess: parse_sess,
-            ecfg: ecfg,
+            parse_sess,
+            ecfg,
             crate_root: None,
-            resolver: resolver,
+            resolver,
             resolve_err_count: 0,
             current_expansion: ExpansionData {
                 mark: Mark::root(),
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index de0538e38b3..cbdd0013593 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -366,7 +366,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         path.segments.push(ast::PathSegment {
             identifier: ident.node,
             span: ident.span,
-            parameters: parameters,
+            parameters,
         });
 
         (ast::QSelf {
@@ -377,15 +377,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
         ast::MutTy {
-            ty: ty,
-            mutbl: mutbl
+            ty,
+            mutbl,
         }
     }
 
     fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty> {
         P(ast::Ty {
             id: ast::DUMMY_NODE_ID,
-            span: span,
+            span,
             node: ty
         })
     }
@@ -444,15 +444,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             ident: id,
             id: ast::DUMMY_NODE_ID,
             attrs: attrs.into(),
-            bounds: bounds,
-            default: default,
-            span: span
+            bounds,
+            default,
+            span,
         }
     }
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
         ast::TraitRef {
-            path: path,
+            path,
             ref_id: ast::DUMMY_NODE_ID,
         }
     }
@@ -461,7 +461,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::PolyTraitRef {
             bound_lifetimes: Vec::new(),
             trait_ref: self.trait_ref(path),
-            span: span,
+            span,
         }
     }
 
@@ -482,7 +482,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::LifetimeDef {
             attrs: attrs.into(),
             lifetime: self.lifetime(span, ident),
-            bounds: bounds
+            bounds,
         }
     }
 
@@ -511,7 +511,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             self.pat_ident(sp, ident)
         };
         let local = P(ast::Local {
-            pat: pat,
+            pat,
             ty: None,
             init: Some(ex),
             id: ast::DUMMY_NODE_ID,
@@ -539,7 +539,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             self.pat_ident(sp, ident)
         };
         let local = P(ast::Local {
-            pat: pat,
+            pat,
             ty: Some(typ),
             init: Some(ex),
             id: ast::DUMMY_NODE_ID,
@@ -560,13 +560,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             ty: Some(ty),
             init: None,
             id: ast::DUMMY_NODE_ID,
-            span: span,
+            span,
             attrs: ast::ThinVec::new(),
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             node: ast::StmtKind::Local(local),
-            span: span,
+            span,
         }
     }
 
@@ -587,18 +587,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
     fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
         P(ast::Block {
-           stmts: stmts,
+           stmts,
            id: ast::DUMMY_NODE_ID,
            rules: BlockCheckMode::Default,
-           span: span,
+           span,
         })
     }
 
     fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr> {
         P(ast::Expr {
             id: ast::DUMMY_NODE_ID,
-            node: node,
-            span: span,
+            node,
+            span,
             attrs: ast::ThinVec::new(),
         })
     }
@@ -672,7 +672,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::Field {
             ident: respan(span, name),
             expr: e,
-            span: span,
+            span,
             is_shorthand: false,
             attrs: ast::ThinVec::new(),
         }
@@ -876,7 +876,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
             attrs: vec![],
-            pats: pats,
+            pats,
             guard: None,
             body: expr
         }
@@ -954,7 +954,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {
         let arg_pat = self.pat_ident(span, ident);
         ast::Arg {
-            ty: ty,
+            ty,
             pat: arg_pat,
             id: ast::DUMMY_NODE_ID
         }
@@ -963,7 +963,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     // FIXME unused self
     fn fn_decl(&self, inputs: Vec<ast::Arg>, output: P<ast::Ty>) -> P<ast::FnDecl> {
         P(ast::FnDecl {
-            inputs: inputs,
+            inputs,
             output: ast::FunctionRetTy::Ty(output),
             variadic: false
         })
@@ -975,11 +975,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         // Rust coding conventions
         P(ast::Item {
             ident: name,
-            attrs: attrs,
+            attrs,
             id: ast::DUMMY_NODE_ID,
-            node: node,
+            node,
             vis: ast::Visibility::Inherited,
-            span: span,
+            span,
             tokens: None,
         })
     }
@@ -1022,7 +1022,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let fields: Vec<_> = tys.into_iter().map(|ty| {
             ast::StructField {
                 span: ty.span,
-                ty: ty,
+                ty,
                 ident: None,
                 vis: ast::Visibility::Inherited,
                 attrs: Vec::new(),
@@ -1038,7 +1038,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
         respan(span,
                ast::Variant_ {
-                   name: name,
+                   name,
                    attrs: Vec::new(),
                    data: vdata,
                    disr_expr: None,
@@ -1081,7 +1081,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             attrs,
             ast::ItemKind::Mod(ast::Mod {
                 inner: inner_span,
-                items: items,
+                items,
             })
         )
     }
@@ -1147,7 +1147,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             ident: keywords::Invalid.ident(),
             attrs: vec![],
             node: ast::ItemKind::Use(vp),
-            vis: vis,
+            vis,
             span: sp,
             tokens: None,
         })
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9625602fa4a..d1172b1b2ce 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -303,7 +303,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                             kind: InvocationKind::Derive { path: path.clone(), item: item },
                             expansion_kind: invoc.expansion_kind,
                             expansion_data: ExpansionData {
-                                mark: mark,
+                                mark,
                                 ..invoc.expansion_data.clone()
                             },
                         });
@@ -579,7 +579,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let pretty_name = Symbol::intern(&format!("derive({})", path));
         let span = path.span;
         let attr = ast::Attribute {
-            path: path, tokens: TokenStream::empty(), span: span,
+            path, span,
+            tokens: TokenStream::empty(),
             // irrelevant:
             id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
         };
@@ -714,10 +715,10 @@ 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);
         self.invocations.push(Invocation {
-            kind: kind,
-            expansion_kind: expansion_kind,
+            kind,
+            expansion_kind,
             expansion_data: ExpansionData {
-                mark: mark,
+                mark,
                 depth: self.cx.current_expansion.depth + 1,
                 ..self.cx.current_expansion.clone()
             },
@@ -876,7 +877,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
                 item.and_then(|item| match item.node {
                     ItemKind::Mac(mac) => {
                         self.collect(ExpansionKind::Items, InvocationKind::Bang {
-                            mac: mac,
+                            mac,
                             ident: Some(item.ident),
                             span: item.span,
                         }).make_items()
@@ -1035,7 +1036,7 @@ macro_rules! feature_tests {
 impl<'feat> ExpansionConfig<'feat> {
     pub fn default(crate_name: String) -> ExpansionConfig<'static> {
         ExpansionConfig {
-            crate_name: crate_name,
+            crate_name,
             features: None,
             recursion_limit: 1024,
             trace_mac: false,
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index e3377c1d8de..4fc2b92d3cd 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -35,7 +35,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
     let vis = ast::Visibility::Inherited;
     let span = DUMMY_SP;
     let expr_placeholder = || P(ast::Expr {
-        id: id, span: span,
+        id, span,
         attrs: ast::ThinVec::new(),
         node: ast::ExprKind::Mac(mac_placeholder()),
     });
@@ -44,30 +44,30 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
         ExpansionKind::Expr => Expansion::Expr(expr_placeholder()),
         ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())),
         ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item {
-            id: id, span: span, ident: ident, vis: vis, attrs: attrs,
+            id, span, ident, vis, attrs,
             node: ast::ItemKind::Mac(mac_placeholder()),
             tokens: None,
         }))),
         ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem {
-            id: id, span: span, ident: ident, attrs: attrs,
+            id, span, ident, attrs,
             node: ast::TraitItemKind::Macro(mac_placeholder()),
             tokens: None,
         })),
         ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem {
-            id: id, span: span, ident: ident, vis: vis, attrs: attrs,
+            id, span, ident, vis, attrs,
             node: ast::ImplItemKind::Macro(mac_placeholder()),
             defaultness: ast::Defaultness::Final,
             tokens: None,
         })),
         ExpansionKind::Pat => Expansion::Pat(P(ast::Pat {
-            id: id, span: span, node: ast::PatKind::Mac(mac_placeholder()),
+            id, span, node: ast::PatKind::Mac(mac_placeholder()),
         })),
         ExpansionKind::Ty => Expansion::Ty(P(ast::Ty {
-            id: id, span: span, node: ast::TyKind::Mac(mac_placeholder()),
+            id, span, node: ast::TyKind::Mac(mac_placeholder()),
         })),
         ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({
             let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new()));
-            ast::Stmt { id: id, span: span, node: ast::StmtKind::Mac(mac) }
+            ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
         })),
     }
 }
@@ -81,9 +81,9 @@ pub struct PlaceholderExpander<'a, 'b: 'a> {
 impl<'a, 'b> PlaceholderExpander<'a, 'b> {
     pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
         PlaceholderExpander {
-            cx: cx,
+            cx,
             expansions: HashMap::new(),
-            monotonic: monotonic,
+            monotonic,
         }
     }
 
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 9907dfe341e..c3f3a59c302 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -383,7 +383,7 @@ pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> {
             }
             TokenTree::Token(span, token::CloseDelim(delim)) => {
                 let tree = TokenTree::Delimited(span, Delimited {
-                    delim: delim,
+                    delim,
                     tts: result.into_iter().map(TokenStream::from).collect::<TokenStream>().into(),
                 });
                 result = results.pop().unwrap();
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 146bd5d9856..405d06dafbf 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -178,7 +178,7 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
         sep: None,
         idx: 0,
         up: None,
-        matches: matches,
+        matches,
         match_lo: 0,
         match_cur: 0,
         match_hi: match_idx_hi,
@@ -374,7 +374,7 @@ fn inner_parse_loop(sess: &ParseSess,
                         stack: vec![],
                         sep: seq.separator.clone(),
                         idx: 0,
-                        matches: matches,
+                        matches,
                         match_lo: item.match_cur,
                         match_cur: item.match_cur,
                         match_hi: item.match_cur + seq.num_captures,
@@ -400,7 +400,7 @@ fn inner_parse_loop(sess: &ParseSess,
                     let idx = item.idx;
                     item.stack.push(MatcherTtFrame {
                         elts: lower_elts,
-                        idx: idx,
+                        idx,
                     });
                     item.idx = 0;
                     cur_items.push(item);
@@ -599,9 +599,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
                 panic!(FatalError)
             }
         },
-        "path" => {
-            token::NtPath(panictry!(p.parse_path(PathStyle::Type)))
-        },
+        "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
         "meta" => token::NtMeta(panictry!(p.parse_meta_item())),
         "vis" => token::NtVis(panictry!(p.parse_visibility(true))),
         // this is not supposed to happen, since it has been checked
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 7b3fe2bd993..983b19c5bf0 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -271,9 +271,9 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
 
     let expander: Box<_> = Box::new(MacroRulesMacroExpander {
         name: def.ident,
-        lhses: lhses,
-        rhses: rhses,
-        valid: valid,
+        lhses,
+        rhses,
+        valid,
     });
 
     if body.legacy {
diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index 6fdcadd1dde..012d4a54b36 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -191,8 +191,8 @@ fn parse_tree<I>(tree: tokenstream::TokenTree,
                 let name_captures = macro_parser::count_names(&sequence);
                 TokenTree::Sequence(span, Rc::new(SequenceRepetition {
                     tts: sequence,
-                    separator: separator,
-                    op: op,
+                    separator,
+                    op,
                     num_captures: name_captures,
                 }))
             }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 2b8a733b852..09574d5ba12 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -112,8 +112,8 @@ macro_rules! declare_features {
 // was set. This is most important for knowing when a particular feature became
 // stable (active).
 //
-// NB: The featureck.py script parses this information directly out of the source
-// so take care when modifying it.
+// NB: tools/tidy/src/features.rs parses this information directly out of the
+// source, so take care when modifying it.
 
 declare_features! (
     (active, asm, "1.0.0", Some(29722)),
@@ -345,9 +345,6 @@ declare_features! (
     // Allows `repr(align(u16))` struct attribute (RFC 1358)
     (active, repr_align, "1.17.0", Some(33626)),
 
-    // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
-    (active, rvalue_static_promotion, "1.15.1", Some(38865)),
-
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289)),
 
@@ -375,6 +372,9 @@ declare_features! (
 
     // #[doc(cfg(...))]
     (active, doc_cfg, "1.21.0", Some(43781)),
+
+    // allow `#[must_use]` on functions (RFC 1940)
+    (active, fn_must_use, "1.21.0", Some(43302)),
 );
 
 declare_features! (
@@ -457,6 +457,8 @@ declare_features! (
     (accepted, associated_consts, "1.20.0", Some(29646)),
     // Usage of the `compile_error!` macro
     (accepted, compile_error, "1.20.0", Some(40872)),
+    // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
+    (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -916,20 +918,27 @@ struct Context<'a> {
 }
 
 macro_rules! gate_feature_fn {
-    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
-        let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
+    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
+        let (cx, has_feature, span,
+             name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
         let has_feature: bool = has_feature(&$cx.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable() {
-            emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
+            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
+                .emit();
         }
     }}
 }
 
 macro_rules! gate_feature {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
-    }
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, GateStrength::Hard)
+    };
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, $level)
+    };
 }
 
 impl<'a> Context<'a> {
@@ -939,7 +948,7 @@ impl<'a> Context<'a> {
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
-                    gate_feature_fn!(self, has_feature, attr.span, name, desc);
+                    gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
                 }
                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
                 return;
@@ -1009,13 +1018,26 @@ pub enum GateIssue {
     Library(Option<u32>)
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum GateStrength {
+    /// A hard error. (Most feature gates should use this.)
+    Hard,
+    /// Only a warning. (Use this only as backwards-compatibility demands.)
+    Soft,
+}
+
 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
                         explain: &str) {
     feature_err(sess, feature, span, issue, explain).emit();
 }
 
 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
-                   explain: &str) -> DiagnosticBuilder<'a> {
+                       explain: &str) -> DiagnosticBuilder<'a> {
+    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
+}
+
+fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
+                           explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
     let diag = &sess.span_diagnostic;
 
     let issue = match issue {
@@ -1023,10 +1045,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
         GateIssue::Library(lib) => lib,
     };
 
-    let mut err = if let Some(n) = issue {
-        diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
+    let explanation = if let Some(n) = issue {
+        format!("{} (see issue #{})", explain, n)
     } else {
-        diag.struct_span_err(span, explain)
+        explain.to_owned()
+    };
+
+    let mut err = match level {
+        GateStrength::Hard => diag.struct_span_err(span, &explanation),
+        GateStrength::Soft => diag.struct_span_warn(span, &explanation),
     };
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -1036,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
                           feature));
     }
 
+    // If we're on stable and only emitting a "soft" warning, add a note to
+    // clarify that the feature isn't "on" (rather than being on but
+    // warning-worthy).
+    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
+        err.help("a nightly build of the compiler is required to enable this feature");
+    }
+
     err
+
 }
 
 const EXPLAIN_BOX_SYNTAX: &'static str =
@@ -1093,6 +1128,12 @@ macro_rules! gate_feature_post {
         if !span.allows_unstable() {
             gate_feature!(cx.context, $feature, span, $explain)
         }
+    }};
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
+        let (cx, span) = ($cx, $span);
+        if !span.allows_unstable() {
+            gate_feature!(cx.context, $feature, span, $explain, $level)
+        }
     }}
 }
 
@@ -1235,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                         function may change over time, for now \
                                         a top-level `fn main()` is required");
                 }
+                if attr::contains_name(&i.attrs[..], "must_use") {
+                    gate_feature_post!(&self, fn_must_use, i.span,
+                                       "`#[must_use]` on functions is experimental",
+                                       GateStrength::Soft);
+                }
             }
 
             ast::ItemKind::Struct(..) => {
@@ -1272,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                     and possibly buggy");
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
+            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
                                        i.span,
@@ -1285,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                                        i.span,
                                        "specialization is unstable");
                 }
+
+                for impl_item in impl_items {
+                    if let ast::ImplItemKind::Method(..) = impl_item.node {
+                        if attr::contains_name(&impl_item.attrs[..], "must_use") {
+                            gate_feature_post!(&self, fn_must_use, impl_item.span,
+                                               "`#[must_use]` on methods is experimental",
+                                               GateStrength::Soft);
+                        }
+                    }
+                }
             }
 
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
@@ -1576,9 +1632,9 @@ pub fn check_crate(krate: &ast::Crate,
                    unstable: UnstableFeatures) {
     maybe_stage_features(&sess.span_diagnostic, krate, unstable);
     let ctx = Context {
-        features: features,
+        features,
         parse_sess: sess,
-        plugin_attributes: plugin_attributes,
+        plugin_attributes,
     };
     visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
 }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index a54e2573af4..6fd0a2eab42 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -375,8 +375,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyKind::BareFn(f) => {
                 TyKind::BareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
                     lifetimes: fld.fold_lifetime_defs(lifetimes),
-                    unsafety: unsafety,
-                    abi: abi,
+                    unsafety,
+                    abi,
                     decl: fld.fold_fn_decl(decl)
                 }))
             }
@@ -387,7 +387,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                 let qself = qself.map(|QSelf { ty, position }| {
                     QSelf {
                         ty: fld.fold_ty(ty),
-                        position: position
+                        position,
                     }
                 });
                 TyKind::Path(qself, fld.fold_path(path))
@@ -415,7 +415,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
 pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
                                         fld: &mut T) -> ForeignMod {
     ForeignMod {
-        abi: abi,
+        abi,
         items: items.move_map(|x| fld.fold_foreign_item(x)),
     }
 }
@@ -658,7 +658,7 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
             FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(fld.fold_ty(ty)),
             FunctionRetTy::Default(span) => FunctionRetTy::Default(fld.new_span(span)),
         },
-        variadic: variadic
+        variadic,
     })
 }
 
@@ -745,7 +745,7 @@ pub fn noop_fold_where_clause<T: Folder>(
         predicates: predicates.move_map(|predicate| {
             fld.fold_where_predicate(predicate)
         }),
-        span: span,
+        span,
     }
 }
 
@@ -846,7 +846,7 @@ pub fn noop_fold_field<T: Folder>(f: Field, folder: &mut T) -> Field {
 pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy {
     MutTy {
         ty: folder.fold_ty(ty),
-        mutbl: mutbl,
+        mutbl,
     }
 }
 
@@ -864,7 +864,7 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
     b.map(|Block {id, stmts, rules, span}| Block {
         id: folder.new_id(id),
         stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
-        rules: rules,
+        rules,
         span: folder.new_span(span),
     })
 }
@@ -998,10 +998,10 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
                                   folder: &mut T) -> Crate {
     let mut items = folder.fold_item(P(ast::Item {
         ident: keywords::Invalid.ident(),
-        attrs: attrs,
+        attrs,
         id: ast::DUMMY_NODE_ID,
         vis: ast::Visibility::Public,
-        span: span,
+        span,
         node: ast::ItemKind::Mod(module),
         tokens: None,
     })).into_iter();
@@ -1024,9 +1024,9 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
     };
 
     Crate {
-        module: module,
-        attrs: attrs,
-        span: span,
+        module,
+        attrs,
+        span,
     }
 }
 
@@ -1048,7 +1048,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span,
 
         // FIXME: if this is replaced with a call to `folder.fold_tts` it causes
         //        an ICE during resolve... odd!
-        tokens: tokens,
+        tokens,
     }
 }
 
@@ -1264,7 +1264,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                 let qself = qself.map(|QSelf { ty, position }| {
                     QSelf {
                         ty: folder.fold_ty(ty),
-                        position: position
+                        position,
                     }
                 });
                 ExprKind::Path(qself, folder.fold_path(path))
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 695c740f405..37a59411c16 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -11,7 +11,7 @@
 //! A JSON emitter for errors.
 //!
 //! This works by converting errors to a simplified structural format (see the
-//! structs at the start of the file) and then serialising them. These should
+//! structs at the start of the file) and then serializing them. These should
 //! contain as much information about the error as possible.
 //!
 //! The format of the JSON output should be considered *unstable*. For now the
@@ -42,7 +42,7 @@ impl JsonEmitter {
                   code_map: Rc<CodeMap>) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
-            registry: registry,
+            registry,
             cm: code_map,
         }
     }
@@ -56,8 +56,8 @@ impl JsonEmitter {
                registry: Option<Registry>,
                code_map: Rc<CodeMap>) -> JsonEmitter {
         JsonEmitter {
-            dst: dst,
-            registry: registry,
+            dst,
+            registry,
             cm: code_map,
         }
     }
@@ -251,7 +251,7 @@ impl DiagnosticSpan {
             Box::new(DiagnosticSpanMacroExpansion {
                 span: call_site,
                 macro_decl_name: bt.macro_decl_name,
-                def_site_span: def_site_span,
+                def_site_span,
             })
         });
         DiagnosticSpan {
@@ -262,11 +262,11 @@ impl DiagnosticSpan {
             line_end: end.line,
             column_start: start.col.0 + 1,
             column_end: end.col.0 + 1,
-            is_primary: is_primary,
+            is_primary,
             text: DiagnosticSpanLine::from_span(span, je),
             suggested_replacement: suggestion.cloned(),
             expansion: backtrace_step,
-            label: label,
+            label,
         }
     }
 
@@ -351,7 +351,7 @@ impl DiagnosticCode {
 
             DiagnosticCode {
                 code: s,
-                explanation: explanation,
+                explanation,
             }
         })
     }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 43345b02bf6..e3c9f0a9345 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "syntax"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/",
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index c99a09ab24e..48c92873e14 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -141,11 +141,11 @@ impl<'a> Parser<'a> {
 
         Ok(ast::Attribute {
             id: attr::mk_attr_id(),
-            style: style,
-            path: path,
-            tokens: tokens,
+            style,
+            path,
+            tokens,
             is_sugared_doc: false,
-            span: span,
+            span,
         })
     }
 
@@ -244,10 +244,9 @@ impl<'a> Parser<'a> {
     pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
         Ok(if self.eat(&token::Eq) {
             ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?)
-        } else if self.token == token::OpenDelim(token::Paren) {
+        } else if self.eat(&token::OpenDelim(token::Paren)) {
             ast::MetaItemKind::List(self.parse_meta_seq()?)
         } else {
-            self.eat(&token::OpenDelim(token::Paren));
             ast::MetaItemKind::Word
         })
     }
@@ -277,9 +276,8 @@ impl<'a> Parser<'a> {
 
     /// matches meta_seq = ( COMMASEP(meta_item_inner) )
     fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
-        self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
-                                 &token::CloseDelim(token::Paren),
-                                 SeqSep::trailing_allowed(token::Comma),
-                                 |p: &mut Parser<'a>| p.parse_meta_item_inner())
+        self.parse_seq_to_end(&token::CloseDelim(token::Paren),
+                              SeqSep::trailing_allowed(token::Comma),
+                              |p: &mut Parser<'a>| p.parse_meta_item_inner())
     }
 }
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index 8b545d3b909..f65fffebe33 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -192,7 +192,7 @@ fn read_line_comments(rdr: &mut StringReader,
     if !lines.is_empty() {
         comments.push(Comment {
             style: if code_to_the_left { Trailing } else { Isolated },
-            lines: lines,
+            lines,
             pos: p,
         });
     }
@@ -306,8 +306,8 @@ fn read_block_comment(rdr: &mut StringReader,
     }
     debug!("<<< block comment");
     comments.push(Comment {
-        style: style,
-        lines: lines,
+        style,
+        lines,
         pos: p,
     });
 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 09cdf26bf1f..527d2e41396 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -160,18 +160,18 @@ impl<'a> StringReader<'a> {
         let source_text = (*filemap.src.as_ref().unwrap()).clone();
 
         StringReader {
-            sess: sess,
+            sess,
             next_pos: filemap.start_pos,
             pos: filemap.start_pos,
             col: CharPos(0),
             ch: Some('\n'),
-            filemap: filemap,
+            filemap,
             terminator: None,
             save_new_lines_and_multibyte: true,
             // dummy values; not read
             peek_tok: token::Eof,
             peek_span: syntax_pos::DUMMY_SP,
-            source_text: source_text,
+            source_text,
             fatal_errs: Vec::new(),
             token: token::Eof,
             span: syntax_pos::DUMMY_SP,
@@ -546,7 +546,7 @@ impl<'a> StringReader<'a> {
                             };
 
                             Some(TokenAndSpan {
-                                tok: tok,
+                                tok,
                                 sp: self.mk_sp(start_bpos, self.pos),
                             })
                         })
@@ -675,7 +675,7 @@ impl<'a> StringReader<'a> {
             };
 
             Some(TokenAndSpan {
-                tok: tok,
+                tok,
                 sp: self.mk_sp(start_bpos, self.pos),
             })
         })
diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs
index 63a396c14db..ad389ab510a 100644
--- a/src/libsyntax/parse/lexer/tokentrees.rs
+++ b/src/libsyntax/parse/lexer/tokentrees.rs
@@ -114,7 +114,7 @@ impl<'a> StringReader<'a> {
                 }
 
                 Ok(TokenTree::Delimited(span, Delimited {
-                    delim: delim,
+                    delim,
                     tts: tts.into(),
                 }))
             },
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 957164bab79..67b4954a8f1 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -69,7 +69,7 @@ impl ParseSess {
             config: HashSet::new(),
             missing_fragment_specifiers: RefCell::new(HashSet::new()),
             included_mod_stack: RefCell::new(vec![]),
-            code_map: code_map
+            code_map,
         }
     }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 15f05df58b5..90a635fdf44 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -84,7 +84,7 @@ pub enum PathStyle {
     Expr,
     /// In other contexts, notably in types, no ambiguity exists and paths can be written
     /// without the disambiguator, e.g. `x<y>` - unambiguously a path.
-    /// Paths with disambiguators are rejected for now, but may be allowed in the future.
+    /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too.
     Type,
     /// A path with generic arguments disallowed, e.g. `foo::bar::Baz`, used in imports,
     /// visibilities or attributes.
@@ -465,17 +465,17 @@ impl From<P<Expr>> for LhsExpr {
 /// Create a placeholder argument.
 fn dummy_arg(span: Span) -> Arg {
     let spanned = Spanned {
-        span: span,
+        span,
         node: keywords::Invalid.ident()
     };
     let pat = P(Pat {
         id: ast::DUMMY_NODE_ID,
         node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None),
-        span: span
+        span,
     });
     let ty = Ty {
         node: TyKind::Err,
-        span: span,
+        span,
         id: ast::DUMMY_NODE_ID
     };
     Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
@@ -489,7 +489,7 @@ impl<'a> Parser<'a> {
                desugar_doc_comments: bool)
                -> Self {
         let mut parser = Parser {
-            sess: sess,
+            sess,
             token: token::Underscore,
             span: syntax_pos::DUMMY_SP,
             prev_span: syntax_pos::DUMMY_SP,
@@ -497,7 +497,7 @@ impl<'a> Parser<'a> {
             prev_token_kind: PrevTokenKind::Other,
             restrictions: Restrictions::empty(),
             obsolete_set: HashSet::new(),
-            recurse_into_file_modules: recurse_into_file_modules,
+            recurse_into_file_modules,
             directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
             root_module_name: None,
             expected_tokens: Vec::new(),
@@ -508,7 +508,7 @@ impl<'a> Parser<'a> {
                 }),
                 stack: Vec::new(),
             },
-            desugar_doc_comments: desugar_doc_comments,
+            desugar_doc_comments,
             cfg_mods: true,
         };
 
@@ -1216,15 +1216,15 @@ impl<'a> Parser<'a> {
         let (inputs, variadic) = self.parse_fn_args(false, true)?;
         let ret_ty = self.parse_ret_ty()?;
         let decl = P(FnDecl {
-            inputs: inputs,
+            inputs,
             output: ret_ty,
-            variadic: variadic
+            variadic,
         });
         Ok(TyKind::BareFn(P(BareFnTy {
-            abi: abi,
-            unsafety: unsafety,
+            abi,
+            unsafety,
             lifetimes: lifetime_defs,
-            decl: decl
+            decl,
         })))
     }
 
@@ -1312,11 +1312,11 @@ impl<'a> Parser<'a> {
 
             generics.where_clause = self.parse_where_clause()?;
             let sig = ast::MethodSig {
-                unsafety: unsafety,
-                constness: constness,
+                unsafety,
+                constness,
                 decl: d,
-                generics: generics,
-                abi: abi,
+                generics,
+                abi,
             };
 
             let body = match self.token {
@@ -1344,8 +1344,8 @@ impl<'a> Parser<'a> {
         Ok(TraitItem {
             id: ast::DUMMY_NODE_ID,
             ident: name,
-            attrs: attrs,
-            node: node,
+            attrs,
+            node,
             span: lo.to(self.prev_span),
             tokens: None,
         })
@@ -1625,7 +1625,7 @@ impl<'a> Parser<'a> {
 
         Ok(Arg {
             ty: t,
-            pat: pat,
+            pat,
             id: ast::DUMMY_NODE_ID,
         })
     }
@@ -1649,7 +1649,7 @@ impl<'a> Parser<'a> {
         };
         Ok(Arg {
             ty: t,
-            pat: pat,
+            pat,
             id: ast::DUMMY_NODE_ID
         })
     }
@@ -1755,7 +1755,7 @@ impl<'a> Parser<'a> {
         self.expect(&token::ModSep)?;
 
         let qself = QSelf { ty, position: path.segments.len() };
-        self.parse_path_segments(&mut path.segments, style)?;
+        self.parse_path_segments(&mut path.segments, style, true)?;
 
         Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
     }
@@ -1770,16 +1770,26 @@ impl<'a> Parser<'a> {
     /// `a::b::C::<D>` (with disambiguator)
     /// `Fn(Args)` (without disambiguator)
     /// `Fn::(Args)` (with disambiguator)
-    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path>
-    {
-        maybe_whole!(self, NtPath, |x| x);
+    pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
+        self.parse_path_common(style, true)
+    }
+
+    pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
+                             -> PResult<'a, ast::Path> {
+        maybe_whole!(self, NtPath, |path| {
+            if style == PathStyle::Mod &&
+               path.segments.iter().any(|segment| segment.parameters.is_some()) {
+                self.diagnostic().span_err(path.span, "unexpected generic arguments in path");
+            }
+            path
+        });
 
         let lo = self.meta_var_span.unwrap_or(self.span);
         let mut segments = Vec::new();
         if self.eat(&token::ModSep) {
             segments.push(PathSegment::crate_root(lo));
         }
-        self.parse_path_segments(&mut segments, style)?;
+        self.parse_path_segments(&mut segments, style, enable_warning)?;
 
         Ok(ast::Path { segments, span: lo.to(self.prev_span) })
     }
@@ -1804,10 +1814,10 @@ impl<'a> Parser<'a> {
         self.parse_path(style)
     }
 
-    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle)
-                           -> PResult<'a, ()> {
+    fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle,
+                           enable_warning: bool) -> PResult<'a, ()> {
         loop {
-            segments.push(self.parse_path_segment(style)?);
+            segments.push(self.parse_path_segment(style, enable_warning)?);
 
             if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
@@ -1815,7 +1825,8 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
+    fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
+                          -> PResult<'a, PathSegment> {
         let ident_span = self.span;
         let ident = self.parse_path_segment_ident()?;
 
@@ -1835,17 +1846,9 @@ impl<'a> Parser<'a> {
                                       && self.look_ahead(1, |t| is_args_start(t)) {
             // Generic arguments are found - `<`, `(`, `::<` or `::(`.
             let lo = self.span;
-            if self.eat(&token::ModSep) {
-                // These errors are not strictly necessary and may be removed in the future.
-                if style == PathStyle::Type {
-                    let mut err = self.diagnostic().struct_span_err(self.prev_span,
-                        "unnecessary path disambiguator");
-                    err.span_label(self.prev_span, "try removing `::`");
-                    err.emit();
-                } else if self.token == token::OpenDelim(token::Paren) {
-                    self.diagnostic().span_err(self.prev_span,
-                        "`::` is not supported before parenthesized generic arguments")
-                }
+            if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
+                self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
+                                 .span_label(self.prev_span, "try removing `::`").emit();
             }
 
             let parameters = if self.eat_lt() {
@@ -1934,8 +1937,8 @@ impl<'a> Parser<'a> {
         Ok(ast::Field {
             ident: respan(lo.to(hi), fieldname),
             span: lo.to(expr.span),
-            expr: expr,
-            is_shorthand: is_shorthand,
+            expr,
+            is_shorthand,
             attrs: attrs.into(),
         })
     }
@@ -1943,8 +1946,8 @@ impl<'a> Parser<'a> {
     pub fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
         P(Expr {
             id: ast::DUMMY_NODE_ID,
-            node: node,
-            span: span,
+            node,
+            span,
             attrs: attrs.into(),
         })
     }
@@ -1990,8 +1993,8 @@ impl<'a> Parser<'a> {
         P(Expr {
             id: ast::DUMMY_NODE_ID,
             node: ExprKind::Mac(codemap::Spanned {node: m, span: span}),
-            span: span,
-            attrs: attrs,
+            span,
+            attrs,
         })
     }
 
@@ -2006,7 +2009,7 @@ impl<'a> Parser<'a> {
             id: ast::DUMMY_NODE_ID,
             node: ExprKind::Lit(lv_lit),
             span: *span,
-            attrs: attrs,
+            attrs,
         })
     }
 
@@ -2382,7 +2385,7 @@ impl<'a> Parser<'a> {
 
     // Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
-        let segment = self.parse_path_segment(PathStyle::Expr)?;
+        let segment = self.parse_path_segment(PathStyle::Expr, true)?;
         Ok(match self.token {
             token::OpenDelim(token::Paren) => {
                 // Method call `expr.f()`
@@ -2968,6 +2971,18 @@ impl<'a> Parser<'a> {
         }
         let lo = self.prev_span;
         let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?;
+
+        // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
+        // verify that the last statement is either an implicit return (no `;`) or an explicit
+        // return. This won't catch blocks with an explicit `return`, but that would be caught by
+        // the dead code lint.
+        if self.eat_keyword(keywords::Else) || !cond.returns() {
+            let sp = lo.next_point();
+            let mut err = self.diagnostic()
+                .struct_span_err(sp, "missing condition for `if` statemement");
+            err.span_label(sp, "expected if condition here");
+            return Err(err)
+        }
         let thn = self.parse_block()?;
         let mut els: Option<P<Expr>> = None;
         let mut hi = thn.span;
@@ -3153,9 +3168,9 @@ impl<'a> Parser<'a> {
         }
 
         Ok(ast::Arm {
-            attrs: attrs,
-            pats: pats,
-            guard: guard,
+            attrs,
+            pats,
+            guard,
             body: expr,
         })
     }
@@ -3361,7 +3376,7 @@ impl<'a> Parser<'a> {
                                            node: ast::FieldPat {
                                                ident: fieldname,
                                                pat: subpat,
-                                               is_shorthand: is_shorthand,
+                                               is_shorthand,
                                                attrs: attrs.into(),
                                            }
             });
@@ -3597,12 +3612,12 @@ impl<'a> Parser<'a> {
         };
         let init = self.parse_initializer()?;
         Ok(P(ast::Local {
-            ty: ty,
-            pat: pat,
-            init: init,
+            ty,
+            pat,
+            init,
             id: ast::DUMMY_NODE_ID,
             span: lo.to(self.prev_span),
-            attrs: attrs,
+            attrs,
         }))
     }
 
@@ -3618,10 +3633,10 @@ impl<'a> Parser<'a> {
         Ok(StructField {
             span: lo.to(self.prev_span),
             ident: Some(name),
-            vis: vis,
+            vis,
             id: ast::DUMMY_NODE_ID,
-            ty: ty,
-            attrs: attrs,
+            ty,
+            attrs,
         })
     }
 
@@ -3929,7 +3944,7 @@ impl<'a> Parser<'a> {
                 Stmt {
                     id: ast::DUMMY_NODE_ID,
                     span: lo.to(hi),
-                    node: node,
+                    node,
                 }
             } else {
                 // if it has a special ident, it's definitely an item
@@ -3946,7 +3961,7 @@ impl<'a> Parser<'a> {
                 let span = lo.to(hi);
                 Stmt {
                     id: ast::DUMMY_NODE_ID,
-                    span: span,
+                    span,
                     node: StmtKind::Item({
                         self.mk_item(
                             span, id /*id is good here*/,
@@ -4083,7 +4098,7 @@ impl<'a> Parser<'a> {
         }
 
         Ok(P(ast::Block {
-            stmts: stmts,
+            stmts,
             id: ast::DUMMY_NODE_ID,
             rules: s,
             span: lo.to(self.prev_span),
@@ -4227,11 +4242,11 @@ impl<'a> Parser<'a> {
 
         Ok(TyParam {
             attrs: preceding_attrs.into(),
-            ident: ident,
+            ident,
             id: ast::DUMMY_NODE_ID,
-            bounds: bounds,
-            default: default,
-            span: span,
+            bounds,
+            default,
+            span,
         })
     }
 
@@ -4253,8 +4268,8 @@ impl<'a> Parser<'a> {
                 };
                 lifetime_defs.push(LifetimeDef {
                     attrs: attrs.into(),
-                    lifetime: lifetime,
-                    bounds: bounds,
+                    lifetime,
+                    bounds,
                 });
                 if seen_ty_param {
                     self.span_err(self.prev_span,
@@ -4297,7 +4312,7 @@ impl<'a> Parser<'a> {
             self.expect_gt()?;
             Ok(ast::Generics {
                 lifetimes: lifetime_defs,
-                ty_params: ty_params,
+                ty_params,
                 where_clause: WhereClause {
                     id: ast::DUMMY_NODE_ID,
                     predicates: Vec::new(),
@@ -4334,8 +4349,8 @@ impl<'a> Parser<'a> {
                 let ty = self.parse_ty()?;
                 bindings.push(TypeBinding {
                     id: ast::DUMMY_NODE_ID,
-                    ident: ident,
-                    ty: ty,
+                    ident,
+                    ty,
                     span: lo.to(self.prev_span),
                 });
                 seen_binding = true;
@@ -4404,8 +4419,8 @@ impl<'a> Parser<'a> {
                 where_clause.predicates.push(ast::WherePredicate::RegionPredicate(
                     ast::WhereRegionPredicate {
                         span: lo.to(self.prev_span),
-                        lifetime: lifetime,
-                        bounds: bounds,
+                        lifetime,
+                        bounds,
                     }
                 ));
             } else if self.check_type() {
@@ -4427,7 +4442,7 @@ impl<'a> Parser<'a> {
                             span: lo.to(self.prev_span),
                             bound_lifetimes: lifetime_defs,
                             bounded_ty: ty,
-                            bounds: bounds,
+                            bounds,
                         }
                     ));
                 // FIXME: Decide what should be used here, `=` or `==`.
@@ -4437,7 +4452,7 @@ impl<'a> Parser<'a> {
                         ast::WhereEqPredicate {
                             span: lo.to(self.prev_span),
                             lhs_ty: ty,
-                            rhs_ty: rhs_ty,
+                            rhs_ty,
                             id: ast::DUMMY_NODE_ID,
                         }
                     ));
@@ -4518,7 +4533,7 @@ impl<'a> Parser<'a> {
         Ok(P(FnDecl {
             inputs: args,
             output: ret_ty,
-            variadic: variadic
+            variadic,
         }))
     }
 
@@ -4679,7 +4694,7 @@ impl<'a> Parser<'a> {
 
         Ok(P(FnDecl {
             inputs: inputs_captures,
-            output: output,
+            output,
             variadic: false
         }))
     }
@@ -4694,12 +4709,12 @@ impl<'a> Parser<'a> {
     fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
                attrs: Vec<Attribute>) -> P<Item> {
         P(Item {
-            ident: ident,
-            attrs: attrs,
+            ident,
+            attrs,
             id: ast::DUMMY_NODE_ID,
-            node: node,
-            vis: vis,
-            span: span,
+            node,
+            vis,
+            span,
             tokens: None,
         })
     }
@@ -4799,10 +4814,10 @@ impl<'a> Parser<'a> {
             id: ast::DUMMY_NODE_ID,
             span: lo.to(self.prev_span),
             ident: name,
-            vis: vis,
-            defaultness: defaultness,
-            attrs: attrs,
-            node: node,
+            vis,
+            defaultness,
+            attrs,
+            node,
             tokens: None,
         })
     }
@@ -4896,11 +4911,11 @@ impl<'a> Parser<'a> {
             *at_end = true;
             let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
             Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig {
-                generics: generics,
-                abi: abi,
-                unsafety: unsafety,
-                constness: constness,
-                decl: decl
+                generics,
+                abi,
+                unsafety,
+                constness,
+                decl,
              }, body)))
         }
     }
@@ -5151,11 +5166,11 @@ impl<'a> Parser<'a> {
                 let ty = p.parse_ty()?;
                 Ok(StructField {
                     span: lo.to(p.span),
-                    vis: vis,
+                    vis,
                     ident: None,
                     id: ast::DUMMY_NODE_ID,
-                    ty: ty,
-                    attrs: attrs,
+                    ty,
+                    attrs,
                 })
             })?;
 
@@ -5281,7 +5296,7 @@ impl<'a> Parser<'a> {
 
         Ok(ast::Mod {
             inner: inner_lo.to(hi),
-            items: items
+            items,
         })
     }
 
@@ -5403,7 +5418,7 @@ impl<'a> Parser<'a> {
         ModulePath {
             name: mod_name,
             path_exists: default_exists || secondary_exists,
-            result: result,
+            result,
         }
     }
 
@@ -5418,7 +5433,7 @@ impl<'a> Parser<'a> {
                     Some("mod.rs") => DirectoryOwnership::Owned,
                     _ => DirectoryOwnership::UnownedViaMod(true),
                 },
-                path: path,
+                path,
                 warn: false,
             });
         }
@@ -5509,12 +5524,12 @@ impl<'a> Parser<'a> {
         let hi = self.span;
         self.expect(&token::Semi)?;
         Ok(ast::ForeignItem {
-            ident: ident,
-            attrs: attrs,
+            ident,
+            attrs,
             node: ForeignItemKind::Fn(decl, generics),
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
-            vis: vis
+            vis,
         })
     }
 
@@ -5529,12 +5544,12 @@ impl<'a> Parser<'a> {
         let hi = self.span;
         self.expect(&token::Semi)?;
         Ok(ForeignItem {
-            ident: ident,
-            attrs: attrs,
+            ident,
+            attrs,
             node: ForeignItemKind::Static(ty, mutbl),
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
-            vis: vis
+            vis,
         })
     }
 
@@ -5596,7 +5611,7 @@ impl<'a> Parser<'a> {
 
         let prev_span = self.prev_span;
         let m = ast::ForeignMod {
-            abi: abi,
+            abi,
             items: foreign_items
         };
         let invalid = keywords::Invalid.ident();
@@ -5647,7 +5662,7 @@ impl<'a> Parser<'a> {
                 name: ident,
                 attrs: variant_attrs,
                 data: struct_def,
-                disr_expr: disr_expr,
+                disr_expr,
             };
             variants.push(respan(vlo.to(self.prev_span), vr));
 
@@ -6162,7 +6177,7 @@ impl<'a> Parser<'a> {
             let rename = this.parse_rename()?;
             let node = ast::PathListItem_ {
                 name: ident,
-                rename: rename,
+                rename,
                 id: ast::DUMMY_NODE_ID
             };
             Ok(respan(lo.to(this.prev_span), node))
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 3ce9e9d07b3..5c4bf47a6db 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -246,7 +246,7 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
     let n: usize = 55 * linewidth;
     debug!("mk_printer {}", linewidth);
     Printer {
-        out: out,
+        out,
         buf_len: n,
         margin: linewidth as isize,
         space: linewidth as isize,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index e9d11e73837..3be831e828c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -72,7 +72,7 @@ fn rust_printer<'a>(writer: Box<Write+'a>, ann: &'a PpAnn) -> State<'a> {
         literals: vec![].into_iter().peekable(),
         cur_cmnt: 0,
         boxes: Vec::new(),
-        ann: ann,
+        ann,
     }
 }
 
@@ -145,11 +145,11 @@ impl<'a> State<'a> {
         State {
             s: pp::mk_printer(out, DEFAULT_COLUMNS),
             cm: Some(cm),
-            comments: comments,
+            comments,
             literals: literals.unwrap_or_default().into_iter().peekable(),
             cur_cmnt: 0,
             boxes: Vec::new(),
-            ann: ann,
+            ann,
         }
     }
 }
diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs
index 263a4f13c1b..8ab2ba71ec1 100644
--- a/src/libsyntax/show_span.rs
+++ b/src/libsyntax/show_span.rs
@@ -79,8 +79,8 @@ pub fn run(span_diagnostic: &errors::Handler,
         None => return
     };
     let mut v = ShowSpanVisitor {
-        span_diagnostic: span_diagnostic,
-        mode: mode,
+        span_diagnostic,
+        mode,
     };
     visit::walk_crate(&mut v, krate);
 }
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 430976e7d3c..8977d701e5a 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -72,18 +72,18 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
             tokens: TokenStream::empty(),
             id: attr::mk_attr_id(),
             is_sugared_doc: false,
-            span: span,
+            span,
         }],
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
             segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
                 ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
             }).collect(),
-            span: span,
+            span,
         })))),
         id: ast::DUMMY_NODE_ID,
         ident: keywords::Invalid.ident(),
-        span: span,
+        span,
         tokens: None,
     }));
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index c05e166e013..35dc9819529 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -56,13 +56,12 @@ struct Test {
 }
 
 struct TestCtxt<'a> {
-    sess: &'a ParseSess,
     span_diagnostic: &'a errors::Handler,
     path: Vec<Ident>,
     ext_cx: ExtCtxt<'a>,
     testfns: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
-    is_test_crate: bool,
+    is_libtest: bool,
     ctxt: SyntaxContext,
 
     // top-level re-export submodule, filled out after folding is finished
@@ -202,18 +201,18 @@ impl fold::Folder for EntryPointCleaner {
                                                               allow_dead_code_item);
 
                     ast::Item {
-                        id: id,
-                        ident: ident,
+                        id,
+                        ident,
                         attrs: attrs.into_iter()
                             .filter(|attr| {
                                 !attr.check_name("main") && !attr.check_name("start")
                             })
                             .chain(iter::once(allow_dead_code))
                             .collect(),
-                        node: node,
-                        vis: vis,
-                        span: span,
-                        tokens: tokens,
+                        node,
+                        vis,
+                        span,
+                        tokens,
                     }
                 }),
             EntryPointType::None |
@@ -243,7 +242,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
 
     let reexport_mod = ast::Mod {
         inner: DUMMY_SP,
-        items: items,
+        items,
     };
 
     let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports"));
@@ -272,14 +271,15 @@ fn generate_test_harness(sess: &ParseSess,
     let krate = cleaner.fold_crate(krate);
 
     let mark = Mark::fresh(Mark::root());
+
     let mut cx: TestCtxt = TestCtxt {
-        sess: sess,
         span_diagnostic: sd,
         ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
         path: Vec::new(),
         testfns: Vec::new(),
-        reexport_test_harness_main: reexport_test_harness_main,
-        is_test_crate: is_test_crate(&krate),
+        reexport_test_harness_main,
+        // NB: doesn't consider the value of `--crate-name` passed on the command line.
+        is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false),
         toplevel_reexport: None,
         ctxt: SyntaxContext::empty().apply_mark(mark),
     };
@@ -296,7 +296,7 @@ fn generate_test_harness(sess: &ParseSess,
     });
 
     TestHarnessGenerator {
-        cx: cx,
+        cx,
         tests: Vec::new(),
         tested_submods: Vec::new(),
     }.fold_crate(krate)
@@ -454,7 +454,7 @@ mod __test {
 fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
     let id_test = Ident::from_str("test");
     let sp = ignored_span(cx, DUMMY_SP);
-    let (vi, vis, ident) = if cx.is_test_crate {
+    let (vi, vis, ident) = if cx.is_libtest {
         (ast::ItemKind::Use(
             P(nospan(ast::ViewPathSimple(id_test,
                                          path_node(vec![id_test]))))),
@@ -464,10 +464,10 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
     };
     P(ast::Item {
         id: ast::DUMMY_NODE_ID,
-        ident: ident,
+        ident,
         node: vi,
         attrs: vec![],
-        vis: vis,
+        vis,
         span: sp,
         tokens: None,
     })
@@ -608,13 +608,6 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
                    test_descs)
 }
 
-fn is_test_crate(krate: &ast::Crate) -> bool {
-    match attr::find_crate_name(&krate.attrs) {
-        Some(s) if "test" == s.as_str() => true,
-        _ => false
-    }
-}
-
 fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.testfns.len());
 
diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml
index bdcec26cb83..1c470240288 100644
--- a/src/libsyntax_ext/Cargo.toml
+++ b/src/libsyntax_ext/Cargo.toml
@@ -10,7 +10,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 fmt_macros = { path = "../libfmt_macros" }
-log = "0.3"
 proc_macro = { path = "../libproc_macro" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs
index 923e8072f43..3742fb8c804 100644
--- a/src/libsyntax_ext/asm.rs
+++ b/src/libsyntax_ext/asm.rs
@@ -152,8 +152,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
                     outputs.push(ast::InlineAsmOutput {
                         constraint: output.unwrap_or(constraint),
                         expr: out,
-                        is_rw: is_rw,
-                        is_indirect: is_indirect,
+                        is_rw,
+                        is_indirect,
                     });
                 }
             }
@@ -242,14 +242,14 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(ast::InlineAsm {
-            asm: asm,
+            asm,
             asm_str_style: asm_str_style.unwrap(),
-            outputs: outputs,
-            inputs: inputs,
+            outputs,
+            inputs,
             clobbers: clobs,
-            volatile: volatile,
-            alignstack: alignstack,
-            dialect: dialect,
+            volatile,
+            alignstack,
+            dialect,
             ctxt: cx.backtrace(),
         })),
         span: sp,
diff --git a/src/libsyntax_ext/deriving/bounds.rs b/src/libsyntax_ext/deriving/bounds.rs
index efb2fe5eb3b..0bc802283fb 100644
--- a/src/libsyntax_ext/deriving/bounds.rs
+++ b/src/libsyntax_ext/deriving/bounds.rs
@@ -34,9 +34,9 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
     let path = Path::new(v);
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
-        path: path,
+        path,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index 35a2a2513f4..71dd7abfab0 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -77,7 +77,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
     let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::clone::Clone),
         additional_bounds: bounds,
diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs
index eef21492deb..0b57beeae85 100644
--- a/src/libsyntax_ext/deriving/cmp/eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/eq.rs
@@ -28,7 +28,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
     let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]);
     let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)];
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::cmp::Eq),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs
index 9fc3d997585..9b057aacece 100644
--- a/src/libsyntax_ext/deriving/cmp/ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/ord.rs
@@ -26,7 +26,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
     let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::cmp::Ord),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
index f2a050ce971..e635c6bebcd 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
@@ -91,14 +91,14 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
     }
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::cmp::PartialEq),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
         supports_unions: false,
-        methods: methods,
+        methods,
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
index ce4d549d696..e7e1c108760 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs
@@ -59,7 +59,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
         generics: LifetimeBounds::empty(),
         explicit_self: borrowed_explicit_self(),
         args: vec![borrowed_self()],
-        ret_ty: ret_ty,
+        ret_ty,
         attributes: attrs,
         is_unsafe: false,
         unify_fieldless_variants: true,
@@ -82,14 +82,14 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
     };
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: vec![],
         path: path_std!(cx, core::cmp::PartialOrd),
         additional_bounds: vec![],
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
         supports_unions: false,
-        methods: methods,
+        methods,
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 38ed596098b..54d71dd4b48 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -28,7 +28,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
                    Borrowed(None, ast::Mutability::Mutable));
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::fmt::Debug),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs
index 498f2348b80..517221af1d4 100644
--- a/src/libsyntax_ext/deriving/decodable.rs
+++ b/src/libsyntax_ext/deriving/decodable.rs
@@ -57,7 +57,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
     let typaram = &*deriving::hygienic_type_parameter(item, "__D");
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: Path::new_(vec![krate, "Decodable"], None, vec![], true),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs
index 69391f48c22..0c8e3c39395 100644
--- a/src/libsyntax_ext/deriving/default.rs
+++ b/src/libsyntax_ext/deriving/default.rs
@@ -26,7 +26,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
     let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: path_std!(cx, core::default::Default),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 1e19cd99419..c2c862f043f 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -138,7 +138,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
     let typaram = &*deriving::hygienic_type_parameter(item, "__S");
 
     let trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
         path: Path::new_(vec![krate, "Encodable"], None, vec![], true),
         additional_bounds: Vec::new(),
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 3cbc7938bde..a0dd2975ca0 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -23,7 +23,7 @@
 //!   and lifetimes for methods.)
 //! - Additional bounds on the type parameters (`TraitDef.additional_bounds`)
 //!
-//! The most important thing for implementers is the `Substructure` and
+//! The most important thing for implementors is the `Substructure` and
 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
 //! arguments:
 //!
@@ -381,10 +381,10 @@ fn find_type_parameters(ty: &ast::Ty,
     }
 
     let mut visitor = Visitor {
-        ty_param_names: ty_param_names,
+        ty_param_names,
         types: Vec::new(),
-        span: span,
-        cx: cx,
+        span,
+        cx,
     };
 
     visit::Visitor::visit_ty(&mut visitor, ty);
@@ -499,7 +499,7 @@ impl<'a> TraitDef<'a> {
             ast::ImplItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
-                ident: ident,
+                ident,
                 vis: ast::Visibility::Inherited,
                 defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
@@ -596,7 +596,7 @@ impl<'a> TraitDef<'a> {
                         span: self.span,
                         bound_lifetimes: vec![],
                         bounded_ty: ty,
-                        bounds: bounds,
+                        bounds,
                     };
 
                     let predicate = ast::WherePredicate::BoundPredicate(predicate);
@@ -606,10 +606,10 @@ impl<'a> TraitDef<'a> {
         }
 
         let trait_generics = Generics {
-            lifetimes: lifetimes,
-            ty_params: ty_params,
-            where_clause: where_clause,
-            span: span,
+            lifetimes,
+            ty_params,
+            where_clause,
+            span,
         };
 
         // Create the reference to the trait.
@@ -807,11 +807,11 @@ impl<'a> MethodDef<'a> {
                                 fields: &SubstructureFields)
                                 -> P<Expr> {
         let substructure = Substructure {
-            type_ident: type_ident,
+            type_ident,
             method_ident: cx.ident_of(self.name),
-            self_args: self_args,
-            nonself_args: nonself_args,
-            fields: fields,
+            self_args,
+            nonself_args,
+            fields,
         };
         let mut f = self.combine_substructure.borrow_mut();
         let f: &mut CombineSubstructureFunc = &mut *f;
@@ -924,8 +924,8 @@ impl<'a> MethodDef<'a> {
             ident: method_ident,
             node: ast::ImplItemKind::Method(ast::MethodSig {
                                                 generics: fn_generics,
-                                                abi: abi,
-                                                unsafety: unsafety,
+                                                abi,
+                                                unsafety,
                                                 constness:
                                                     dummy_spanned(ast::Constness::NotConst),
                                                 decl: fn_decl,
@@ -985,7 +985,7 @@ impl<'a> MethodDef<'a> {
             let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect();
             first_field.map(|(span, opt_id, field, attrs)| {
                     FieldInfo {
-                        span: span,
+                        span,
                         name: opt_id,
                         self_: field,
                         other: other_fields.iter_mut()
@@ -995,7 +995,7 @@ impl<'a> MethodDef<'a> {
                                 }
                             })
                             .collect(),
-                        attrs: attrs,
+                        attrs,
                     }
                 })
                 .collect()
@@ -1246,7 +1246,7 @@ impl<'a> MethodDef<'a> {
                                     name: opt_ident,
                                     self_: self_getter_expr,
                                     other: others,
-                                    attrs: attrs,
+                                    attrs,
                         }
                     }).collect::<Vec<FieldInfo>>();
 
@@ -1553,7 +1553,7 @@ impl<'a> TraitDef<'a> {
                             span: Span { ctxt: self.span.ctxt, ..pat.span },
                             node: ast::FieldPat {
                                 ident: ident.unwrap(),
-                                pat: pat,
+                                pat,
                                 is_shorthand: false,
                                 attrs: ast::ThinVec::new(),
                             },
diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs
index f5ac1743920..47b5f40832a 100644
--- a/src/libsyntax_ext/deriving/generic/ty.rs
+++ b/src/libsyntax_ext/deriving/generic/ty.rs
@@ -55,10 +55,10 @@ impl<'a> Path<'a> {
                     global: bool)
                     -> Path<'r> {
         Path {
-            path: path,
-            lifetime: lifetime,
-            params: params,
-            global: global,
+            path,
+            lifetime,
+            params,
+            global,
         }
     }
 
@@ -211,14 +211,14 @@ fn mk_ty_param(cx: &ExtCtxt,
 fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, span: Span)
                -> Generics {
     Generics {
-        lifetimes: lifetimes,
-        ty_params: ty_params,
+        lifetimes,
+        ty_params,
         where_clause: ast::WhereClause {
             id: ast::DUMMY_NODE_ID,
             predicates: Vec::new(),
-            span: span,
+            span,
         },
-        span: span,
+        span,
     }
 }
 
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index a341c21d0a1..6c78eea186d 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -30,9 +30,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
 
     let arg = Path::new_local(typaram);
     let hash_trait_def = TraitDef {
-        span: span,
+        span,
         attributes: Vec::new(),
-        path: path,
+        path,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs
index 00dcfc7a587..cd706f14a68 100644
--- a/src/libsyntax_ext/deriving/mod.rs
+++ b/src/libsyntax_ext/deriving/mod.rs
@@ -173,6 +173,6 @@ fn call_intrinsic(cx: &ExtCtxt,
         stmts: vec![cx.stmt_expr(call)],
         id: ast::DUMMY_NODE_ID,
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
-        span: span,
+        span,
     }))
 }
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 16b06424c92..764cedfcf20 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -709,11 +709,11 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
     };
 
     let mut cx = Context {
-        ecx: ecx,
-        args: args,
-        arg_types: arg_types,
-        arg_unique_types: arg_unique_types,
-        names: names,
+        ecx,
+        args,
+        arg_types,
+        arg_unique_types,
+        names,
         curarg: 0,
         arg_index_map: Vec::new(),
         count_args: Vec::new(),
@@ -724,7 +724,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         pieces: Vec::new(),
         str_pieces: Vec::new(),
         all_pieces_simple: true,
-        macsp: macsp,
+        macsp,
         fmtsp: fmt.span,
     };
 
diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs
index 3c802e8334d..99dae29d606 100644
--- a/src/libsyntax_ext/format_foreign.rs
+++ b/src/libsyntax_ext/format_foreign.rs
@@ -265,7 +265,7 @@ pub mod printf {
     /// Returns an iterator over all substitutions in a given string.
     pub fn iter_subs(s: &str) -> Substitutions {
         Substitutions {
-            s: s,
+            s,
         }
     }
 
@@ -553,12 +553,12 @@ pub mod printf {
 
         let f = Format {
             span: start.slice_between(end).unwrap(),
-            parameter: parameter,
-            flags: flags,
-            width: width,
-            precision: precision,
-            length: length,
-            type_: type_,
+            parameter,
+            flags,
+            width,
+            precision,
+            length,
+            type_,
         };
         Some((Substitution::Format(f), end.slice_after()))
     }
@@ -776,7 +776,7 @@ pub mod shell {
     /// Returns an iterator over all substitutions in a given string.
     pub fn iter_subs(s: &str) -> Substitutions {
         Substitutions {
-            s: s,
+            s,
         }
     }
 
@@ -933,7 +933,7 @@ mod strcursor {
     impl<'a> StrCursor<'a> {
         pub fn new_at_start(s: &'a str) -> StrCursor<'a> {
             StrCursor {
-                s: s,
+                s,
                 at: 0,
             }
         }
diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs
index 8b0bb8cb891..81226ba599a 100644
--- a/src/libsyntax_ext/global_asm.rs
+++ b/src/libsyntax_ext/global_asm.rs
@@ -56,7 +56,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
         node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm {
-            asm: asm,
+            asm,
             ctxt: cx.backtrace(),
         })),
         vis: ast::Visibility::Inherited,
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 439538a8b5e..42bbb4ae0cb 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -10,9 +10,6 @@
 
 //! Syntax extensions in the Rust compiler.
 
-#![crate_name = "syntax_ext"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -21,7 +18,6 @@
 #![feature(proc_macro_internals)]
 
 extern crate fmt_macros;
-extern crate log;
 #[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs
index 700386f68fe..a8a54a97ac3 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_registrar.rs
@@ -69,9 +69,9 @@ pub fn modify(sess: &ParseSess,
             attr_macros: Vec::new(),
             bang_macros: Vec::new(),
             in_root: true,
-            handler: handler,
-            is_proc_macro_crate: is_proc_macro_crate,
-            is_test_crate: is_test_crate,
+            handler,
+            is_proc_macro_crate,
+            is_test_crate,
         };
         visit::walk_crate(&mut collect, &krate);
         (collect.derives, collect.attr_macros, collect.bang_macros)
@@ -183,7 +183,7 @@ impl<'a> CollectProcMacros<'a> {
         if self.in_root && item.vis == ast::Visibility::Public {
             self.derives.push(ProcMacroDerive {
                 span: item.span,
-                trait_name: trait_name,
+                trait_name,
                 function_name: item.ident,
                 attrs: proc_attrs,
             });
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index 514cc26666e..919804d7efd 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -161,7 +161,7 @@ impl SyntaxContext {
                 syntax_contexts.push(SyntaxContextData {
                     outer_mark: mark,
                     prev_ctxt: self,
-                    modern: modern,
+                    modern,
                 });
                 SyntaxContext(syntax_contexts.len() as u32 - 1)
             })
@@ -323,8 +323,8 @@ impl NameAndSpan {
     pub fn name(&self) -> Symbol {
         match self.format {
             ExpnFormat::MacroAttribute(s) |
-            ExpnFormat::MacroBang(s) |
-            ExpnFormat::CompilerDesugaring(s) => s,
+            ExpnFormat::MacroBang(s) => s,
+            ExpnFormat::CompilerDesugaring(ref kind) => kind.as_symbol(),
         }
     }
 }
@@ -337,7 +337,27 @@ pub enum ExpnFormat {
     /// e.g. `format!()`
     MacroBang(Symbol),
     /// Desugaring done by the compiler during HIR lowering.
-    CompilerDesugaring(Symbol)
+    CompilerDesugaring(CompilerDesugaringKind)
+}
+
+/// The kind of compiler desugaring.
+#[derive(Clone, Hash, Debug, PartialEq, Eq)]
+pub enum CompilerDesugaringKind {
+    BackArrow,
+    DotFill,
+    QuestionMark,
+}
+
+impl CompilerDesugaringKind {
+    pub fn as_symbol(&self) -> Symbol {
+        use CompilerDesugaringKind::*;
+        let s = match *self {
+            BackArrow => "<-",
+            DotFill => "...",
+            QuestionMark => "?",
+        };
+        Symbol::intern(s)
+    }
 }
 
 impl Encodable for SyntaxContext {
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index e162bc26412..d34dcfa3ed3 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "syntax_pos"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![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/")]
@@ -47,7 +44,7 @@ extern crate serialize;
 extern crate serialize as rustc_serialize; // used by deriving
 
 pub mod hygiene;
-pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan};
+pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
 
 pub mod symbol;
 
@@ -153,6 +150,17 @@ impl Span {
         }
     }
 
+    /// Check if this span arises from a compiler desugaring of kind `kind`.
+    pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
+        match self.ctxt.outer().expn_info() {
+            Some(info) => match info.callee.format {
+                ExpnFormat::CompilerDesugaring(k) => k == kind,
+                _ => false,
+            },
+            None => false,
+        }
+    }
+
     /// Check if a span is "internal" to a macro in which `unsafe`
     /// can be used without triggering the `unsafe_code` lint
     //  (that is, a macro marked with `#[allow_internal_unsafe]`).
@@ -184,8 +192,8 @@ impl Span {
             if !info.call_site.source_equal(&prev_span) {
                 result.push(MacroBacktrace {
                     call_site: info.call_site,
-                    macro_decl_name: macro_decl_name,
-                    def_site_span: def_site_span,
+                    macro_decl_name,
+                    def_site_span,
                 });
             }
 
@@ -358,7 +366,7 @@ impl MultiSpan {
 
         for &(span, ref label) in &self.span_labels {
             span_labels.push(SpanLabel {
-                span: span,
+                span,
                 is_primary: is_primary(span),
                 label: Some(label.clone())
             });
@@ -367,7 +375,7 @@ impl MultiSpan {
         for &span in &self.primary_spans {
             if !span_labels.iter().any(|sl| sl.span == span) {
                 span_labels.push(SpanLabel {
-                    span: span,
+                    span,
                     is_primary: true,
                     label: None
                 });
@@ -556,16 +564,16 @@ impl Decodable for FileMap {
             let multibyte_chars: Vec<MultiByteChar> =
                 d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
             Ok(FileMap {
-                name: name,
-                name_was_remapped: name_was_remapped,
+                name,
+                name_was_remapped,
                 // `crate_of_origin` has to be set by the importer.
                 // This value matches up with rustc::hir::def_id::INVALID_CRATE.
                 // That constant is not available here unfortunately :(
                 crate_of_origin: ::std::u32::MAX - 1,
-                start_pos: start_pos,
-                end_pos: end_pos,
+                start_pos,
+                end_pos,
                 src: None,
-                src_hash: src_hash,
+                src_hash,
                 external_src: RefCell::new(ExternalSource::AbsentOk),
                 lines: RefCell::new(lines),
                 multibyte_chars: RefCell::new(multibyte_chars)
@@ -594,13 +602,13 @@ impl FileMap {
         let end_pos = start_pos.to_usize() + src.len();
 
         FileMap {
-            name: name,
-            name_was_remapped: name_was_remapped,
+            name,
+            name_was_remapped,
             crate_of_origin: 0,
             src: Some(Rc::new(src)),
-            src_hash: src_hash,
+            src_hash,
             external_src: RefCell::new(ExternalSource::Unneeded),
-            start_pos: start_pos,
+            start_pos,
             end_pos: Pos::from_usize(end_pos),
             lines: RefCell::new(Vec::new()),
             multibyte_chars: RefCell::new(Vec::new()),
@@ -687,8 +695,8 @@ impl FileMap {
     pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) {
         assert!(bytes >=2 && bytes <= 4);
         let mbc = MultiByteChar {
-            pos: pos,
-            bytes: bytes,
+            pos,
+            bytes,
         };
         self.multibyte_chars.borrow_mut().push(mbc);
     }
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index 4864e4581fa..ad0e582b1c3 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -40,9 +40,6 @@
 //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![crate_name = "term"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 68cfc7033ef..c5e68eed407 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -231,7 +231,7 @@ impl<T: Write + Send> TerminfoTerminal<T> {
         };
 
         TerminfoTerminal {
-            out: out,
+            out,
             ti: terminfo,
             num_colors: nc,
         }
diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs
index 8d1ba378521..0cdea64db8b 100644
--- a/src/libterm/terminfo/parser/compiled.rs
+++ b/src/libterm/terminfo/parser/compiled.rs
@@ -337,8 +337,8 @@ pub fn msys_terminfo() -> TermInfo {
     TermInfo {
         names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version
         bools: HashMap::new(),
-        numbers: numbers,
-        strings: strings,
+        numbers,
+        strings,
     }
 }
 
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index bf71b11fc77..642eb285564 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -23,10 +23,11 @@
 // running tests while providing a base that other test frameworks may
 // build off of.
 
+// NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to
+// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
+// cargo) to detect this crate.
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "27812")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![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/",
@@ -34,12 +35,14 @@
 #![deny(warnings)]
 
 #![feature(asm)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
+#![feature(staged_api)]
 
 extern crate getopts;
 extern crate term;
+#[cfg(unix)]
 extern crate libc;
 extern crate panic_unwind;
 
@@ -235,8 +238,8 @@ pub struct Metric {
 impl Metric {
     pub fn new(value: f64, noise: f64) -> Metric {
         Metric {
-            value: value,
-            noise: noise,
+            value,
+            noise,
         }
     }
 }
@@ -492,17 +495,17 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     };
 
     let test_opts = TestOpts {
-        list: list,
-        filter: filter,
+        list,
+        filter,
         filter_exact: exact,
-        run_ignored: run_ignored,
-        run_tests: run_tests,
-        bench_benchmarks: bench_benchmarks,
-        logfile: logfile,
-        nocapture: nocapture,
-        color: color,
-        quiet: quiet,
-        test_threads: test_threads,
+        run_ignored,
+        run_tests,
+        bench_benchmarks,
+        logfile,
+        nocapture,
+        color,
+        quiet,
+        test_threads,
         skip: matches.opt_strs("skip"),
         options: Options::new(),
     };
@@ -565,8 +568,8 @@ impl<T: Write> ConsoleTestState<T> {
         };
 
         Ok(ConsoleTestState {
-            out: out,
-            log_out: log_out,
+            out,
+            log_out,
             use_color: use_color(opts),
             quiet: opts.quiet,
             total: 0,
@@ -1330,7 +1333,7 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
                 let TestDescAndFn {desc, testfn} = test;
                 Some(TestDescAndFn {
                     desc: TestDesc { ignore: false, ..desc },
-                    testfn: testfn,
+                    testfn,
                 })
             } else {
                 None
@@ -1367,7 +1370,7 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
         };
         TestDescAndFn {
             desc: x.desc,
-            testfn: testfn,
+            testfn,
         }
     }).collect()
 }
@@ -1527,8 +1530,8 @@ impl MetricMap {
     /// negative direction represents a regression.
     pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) {
         let m = Metric {
-            value: value,
-            noise: noise,
+            value,
+            noise,
         };
         let MetricMap(ref mut map) = *self;
         map.insert(name.to_owned(), m);
@@ -1689,7 +1692,7 @@ pub mod bench {
                 let mb_s = bs.bytes * 1000 / ns_iter;
 
                 BenchSamples {
-                    ns_iter_summ: ns_iter_summ,
+                    ns_iter_summ,
                     mb_s: mb_s as usize,
                 }
             }
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index be9aa6c5d40..dc1464b905b 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -16,7 +16,7 @@ fn main() {
 
     if target.contains("linux") {
         if target.contains("musl") && !target.contains("mips") {
-            println!("cargo:rustc-link-lib=static=unwind");
+            // musl is handled in lib.rs
         } else if !target.contains("android") {
             println!("cargo:rustc-link-lib=gcc_s");
         }
@@ -41,5 +41,7 @@ fn main() {
         println!("cargo:rustc-link-lib=unwind");
     } else if target.contains("haiku") {
         println!("cargo:rustc-link-lib=gcc_s");
+    } else if target.contains("redox") {
+        println!("cargo:rustc-link-lib=gcc");
     }
 }
diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs
index d4d52322ada..461b49aa363 100644
--- a/src/libunwind/lib.rs
+++ b/src/libunwind/lib.rs
@@ -9,12 +9,11 @@
 // except according to those terms.
 
 #![no_std]
-#![crate_name = "unwind"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![deny(warnings)]
 
 #![feature(cfg_target_vendor)]
+#![feature(link_cfg)]
 #![feature(staged_api)]
 #![feature(unwind_attributes)]
 #![feature(static_nobundle)]
@@ -28,3 +27,8 @@ extern crate libc;
 mod libunwind;
 #[cfg(not(target_env = "msvc"))]
 pub use libunwind::*;
+
+#[cfg(all(target_env = "musl", not(target_arch = "mips")))]
+#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
+#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
+extern {}
diff --git a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
index edbb77fe390..bb292e2e52a 100644
--- a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
+++ b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
@@ -15,6 +15,7 @@
 // libsyntax is not compiled for it.
 
 #![deny(plugin_as_library)]
+#![allow(unused_extern_crates)]
 
 extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
 
diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs
index 89227f6b010..996a6b97cd9 100644
--- a/src/test/compile-fail/E0254.rs
+++ b/src/test/compile-fail/E0254.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs
index 60bcd2ae076..c285c4d9e00 100644
--- a/src/test/compile-fail/E0259.rs
+++ b/src/test/compile-fail/E0259.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc, libc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs
index 5e802bbbe3d..ad8888e58f7 100644
--- a/src/test/compile-fail/E0260.rs
+++ b/src/test/compile-fail/E0260.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs
index 1f9dfdb1847..847393ba2b8 100644
--- a/src/test/compile-fail/associated-types-eq-expr-path.rs
+++ b/src/test/compile-fail/associated-types-eq-expr-path.rs
@@ -22,5 +22,5 @@ impl Foo for isize {
 
 pub fn main() {
     let x: isize = Foo::<A=usize>::bar();
-    //~^ ERROR unexpected binding of associated item in expression path
+    //~^ ERROR associated type bindings are not allowed here
 }
diff --git a/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs
new file mode 100644
index 00000000000..fc4bca865c9
--- /dev/null
+++ b/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs
@@ -0,0 +1,9 @@
+// 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.
diff --git a/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs
index fbb3824cd40..f7514df800d 100644
--- a/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs
@@ -11,10 +11,12 @@
 // Test lifetimes are linked properly when we take reference
 // to interior.
 
+fn id<T>(x: T) -> T { x }
+
 struct Foo(isize);
 
 fn foo<'a>() -> &'a isize {
-    let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough
+    let &Foo(ref x) = &id(Foo(3)); //~ ERROR borrowed value does not live long enough
     x
 }
 
diff --git a/src/test/compile-fail/enable-unstable-lib-feature.rs b/src/test/compile-fail/enable-unstable-lib-feature.rs
index c65b2366bf1..bc9e2345f0e 100644
--- a/src/test/compile-fail/enable-unstable-lib-feature.rs
+++ b/src/test/compile-fail/enable-unstable-lib-feature.rs
@@ -16,6 +16,7 @@
 #![deny(non_snake_case)] // To trigger a hard error
 
 // Shouldn't generate a warning about unstable features
+#[allow(unused_extern_crates)]
 extern crate stability_cfg2;
 
 pub fn BOGUS() { } //~ ERROR
diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/compile-fail/feature-gate-fn_must_use.rs
new file mode 100644
index 00000000000..2dd6b904072
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-fn_must_use.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.
+
+#![feature(rustc_attrs)]
+
+struct MyStruct;
+
+impl MyStruct {
+    #[must_use]
+    fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
+}
+
+#[must_use]
+fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
+
+
+// Feature gates are tidy-required to have a specially named (or
+// comment-annotated) compile-fail test (which MUST fail), but for
+// backwards-compatibility reasons, we want `#[must_use]` on functions to be
+// compilable even if the `fn_must_use` feature is absent, thus necessitating
+// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
+// dilemma until a superior solution can be devised.
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 29a2b0609fc..204190d64ac 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -680,6 +680,7 @@ mod must_use {
     mod inner { #![must_use="1400"] }
 
     #[must_use = "1400"] fn f() { }
+    //~^ WARN `#[must_use]` on functions is experimental
 
     #[must_use = "1400"] struct S;
 
diff --git a/src/test/compile-fail/foreign-fn-return-lifetime.rs b/src/test/compile-fail/foreign-fn-return-lifetime.rs
new file mode 100644
index 00000000000..da77066150c
--- /dev/null
+++ b/src/test/compile-fail/foreign-fn-return-lifetime.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.
+
+extern "C" {
+    fn g(_: &u8) -> &u8; // OK
+    fn f() -> &u8; //~ ERROR missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-11493.rs b/src/test/compile-fail/issue-11493.rs
index 333ff7118d4..3045c06ca4c 100644
--- a/src/test/compile-fail/issue-11493.rs
+++ b/src/test/compile-fail/issue-11493.rs
@@ -10,7 +10,9 @@
 
 // This file must never have a trailing newline
 
+fn id<T>(x: T) -> T { x }
+
 fn main() {
     let x = Some(3);
-    let y = x.as_ref().unwrap_or(&5); //~ ERROR: borrowed value does not live long enough
+    let y = x.as_ref().unwrap_or(&id(5)); //~ ERROR: borrowed value does not live long enough
 }
diff --git a/src/test/compile-fail/issue-12567.rs b/src/test/compile-fail/issue-12567.rs
index 15d9a318d29..30cdd07b399 100644
--- a/src/test/compile-fail/issue-12567.rs
+++ b/src/test/compile-fail/issue-12567.rs
@@ -15,12 +15,12 @@ fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
         (&[], &[]) => println!("both empty"),
         (&[], &[hd, ..]) | (&[hd, ..], &[])
             => println!("one empty"),
-        //~^^ ERROR: cannot move out of type `[T]`, a non-copy array
-        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy array
+        //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
         (&[hd1, ..], &[hd2, ..])
             => println!("both nonempty"),
-        //~^^ ERROR: cannot move out of type `[T]`, a non-copy array
-        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy array
+        //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
+        //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
     }
 }
 
diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs
index 45bc5ee07a5..9264305e6ea 100644
--- a/src/test/compile-fail/issue-17545.rs
+++ b/src/test/compile-fail/issue-17545.rs
@@ -10,9 +10,11 @@
 
 #![feature(fn_traits)]
 
+fn id<T>(x: T) -> T { x }
+
 pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
     bar.call((
-        &(), //~ ERROR borrowed value does not live long enough
+        &id(()), //~ ERROR borrowed value does not live long enough
     ));
 }
 fn main() {}
diff --git a/src/test/compile-fail/issue-17718-constants-not-static.rs b/src/test/compile-fail/issue-17718-constants-not-static.rs
index db56d2c6cf3..9b7ed463499 100644
--- a/src/test/compile-fail/issue-17718-constants-not-static.rs
+++ b/src/test/compile-fail/issue-17718-constants-not-static.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 const FOO: usize = 3;
 
-fn foo() -> &'static usize { &FOO }
+fn foo() -> &'static usize { &id(FOO) }
 //~^ ERROR: borrowed value does not live long enough
 
 fn main() {
diff --git a/src/test/compile-fail/issue-27592.rs b/src/test/compile-fail/issue-27592.rs
index ccf5eabc111..731d4fb2bf6 100644
--- a/src/test/compile-fail/issue-27592.rs
+++ b/src/test/compile-fail/issue-27592.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Regression test for issue #27591.
+// Regression test for issue #27592.
 
 fn write<'a, F: ::std::ops::FnOnce()->::std::fmt::Arguments<'a> + 'a>(fcn: F) {
     use std::fmt::Write;
@@ -23,7 +23,7 @@ impl ::std::fmt::Write for Stream {
 }
 
 fn main() {
-    write(|| format_args!("{}", "Hello world"));
+    write(|| format_args!("{}", String::from("Hello world")));
     //~^ ERROR borrowed value does not live long enough
     //~| ERROR borrowed value does not live long enough
 }
diff --git a/src/test/compile-fail/issue-32995.rs b/src/test/compile-fail/issue-32995.rs
index 4b7f82943ba..ffbd0c0c22a 100644
--- a/src/test/compile-fail/issue-32995.rs
+++ b/src/test/compile-fail/issue-32995.rs
@@ -19,15 +19,11 @@ fn main() {
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
-    macro_rules! pathexpr {
-        ($p:path) => { $p }
-    }
-
-    let p = pathexpr!(::std::str()::from_utf8)(b"foo").unwrap();
+    let p = ::std::str::()::from_utf8(b"foo").unwrap();
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
-    let p = pathexpr!(::std::str::from_utf8())(b"foo").unwrap();
+    let p = ::std::str::from_utf8::()(b"foo").unwrap();
     //~^ ERROR parenthesized parameters may only be used with a trait
     //~| WARN previously accepted
 
diff --git a/src/test/compile-fail/issue-36116.rs b/src/test/compile-fail/issue-36116.rs
index 737955b2ff3..3afbfa61984 100644
--- a/src/test/compile-fail/issue-36116.rs
+++ b/src/test/compile-fail/issue-36116.rs
@@ -8,16 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Unnecessary path disambiguator is ok
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+macro_rules! m {
+    ($p: path) => {
+        let _ = $p(0);
+        let _: $p;
+    }
+}
+
 struct Foo<T> {
     _a: T,
 }
 
-fn main() {
-    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
-    //~^ ERROR unnecessary path disambiguator
-    //~| NOTE try removing `::`
+struct S<T>(T);
+
+fn f() {
+    let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); //~ WARN unnecessary path disambiguator
+    let g: Foo::<i32> = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator
 
-    let g: Foo::<i32> = Foo { _a: 42 };
-    //~^ ERROR unnecessary path disambiguator
-    //~| NOTE try removing `::`
+    m!(S::<u8>); // OK, no warning
 }
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/issue-36881.rs b/src/test/compile-fail/issue-36881.rs
index e05dc066199..0f5aa24926b 100644
--- a/src/test/compile-fail/issue-36881.rs
+++ b/src/test/compile-fail/issue-36881.rs
@@ -11,6 +11,7 @@
 // aux-build:issue-36881-aux.rs
 
 fn main() {
+    #[allow(unused_extern_crates)]
     extern crate issue_36881_aux;
     use issue_36881_aux::Foo; //~ ERROR unresolved import
 }
diff --git a/src/test/compile-fail/issue-43424.rs b/src/test/compile-fail/issue-43424.rs
new file mode 100644
index 00000000000..431fc8a5aa2
--- /dev/null
+++ b/src/test/compile-fail/issue-43424.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.
+
+#![allow(unused)]
+
+macro_rules! m {
+    ($attr_path: path) => {
+        #[$attr_path]
+        fn f() {}
+    }
+}
+
+m!(inline<u8>); //~ ERROR: unexpected generic arguments in path
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-43431.rs b/src/test/compile-fail/issue-43431.rs
new file mode 100644
index 00000000000..e9f62152888
--- /dev/null
+++ b/src/test/compile-fail/issue-43431.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.
+
+#![feature(fn_traits)]
+
+trait CallSingle<A, B> {
+    fn call(&self, a: A) -> B where Self: Fn(A) -> B;
+}
+
+impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
+    fn call(&self, a: A) -> B {
+        <Self as Fn(A) -> B>::call(self, (a,))
+        //~^ ERROR associated type bindings are not allowed here
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-43784-associated-type.rs b/src/test/compile-fail/issue-43784-associated-type.rs
new file mode 100644
index 00000000000..94b5c0034a7
--- /dev/null
+++ b/src/test/compile-fail/issue-43784-associated-type.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.
+
+pub trait Partial<X: ?Sized>: Copy {
+}
+
+pub trait Complete {
+    type Assoc: Partial<Self>;
+}
+
+impl<T> Partial<T> for T::Assoc where
+    T: Complete
+{
+}
+
+impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+    type Assoc = T;
+}
diff --git a/src/test/compile-fail/issue-43784-supertrait.rs b/src/test/compile-fail/issue-43784-supertrait.rs
new file mode 100644
index 00000000000..e70df113da3
--- /dev/null
+++ b/src/test/compile-fail/issue-43784-supertrait.rs
@@ -0,0 +1,18 @@
+// 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.
+
+pub trait Partial: Copy {
+}
+
+pub trait Complete: Partial {
+}
+
+impl<T> Partial for T where T: Complete {}
+impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs
index 8443518b3f5..9bc2c021904 100644
--- a/src/test/compile-fail/lint-stability-deprecated.rs
+++ b/src/test/compile-fail/lint-stability-deprecated.rs
@@ -14,7 +14,7 @@
 // aux-build:stability_cfg2.rs
 
 #![warn(deprecated)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_extern_crates)]
 #![feature(staged_api, test_feature, rustc_attrs)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs
index b12ef6277bb..a3cfa134983 100644
--- a/src/test/compile-fail/lint-unused-extern-crate.rs
+++ b/src/test/compile-fail/lint-unused-extern-crate.rs
@@ -12,12 +12,15 @@
 // aux-build:lint_unused_extern_crate2.rs
 // aux-build:lint_unused_extern_crate3.rs
 // aux-build:lint_unused_extern_crate4.rs
+// aux-build:lint_unused_extern_crate5.rs
 
 #![deny(unused_extern_crates)]
 #![allow(unused_variables)]
 #![allow(deprecated)]
 
-extern crate lint_unused_extern_crate4; //~ ERROR: unused extern crate
+extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
+
+pub extern crate lint_unused_extern_crate4; // no error, it is reexported
 
 extern crate lint_unused_extern_crate3; // no error, it is used
 
diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs
index ea2dfca0714..a2778a83130 100644
--- a/src/test/compile-fail/macro-reexport-malformed-1.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-1.rs
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport]  //~ ERROR bad macro reexport
 extern crate std;
diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs
index 844955fb7e6..c5af9e3799d 100644
--- a/src/test/compile-fail/macro-reexport-malformed-2.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-2.rs
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport="foo"]  //~ ERROR bad macro reexport
 extern crate std;
diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs
index 381c22854e6..d72d1ee004e 100644
--- a/src/test/compile-fail/macro-reexport-malformed-3.rs
+++ b/src/test/compile-fail/macro-reexport-malformed-3.rs
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport(foo="bar")]  //~ ERROR bad macro reexport
 extern crate std;
diff --git a/src/test/compile-fail/macro-use-bad-args-1.rs b/src/test/compile-fail/macro-use-bad-args-1.rs
index 39c09c69779..a07cc834411 100644
--- a/src/test/compile-fail/macro-use-bad-args-1.rs
+++ b/src/test/compile-fail/macro-use-bad-args-1.rs
@@ -10,5 +10,6 @@
 
 #![no_std]
 
+#[allow(unused_extern_crates)]
 #[macro_use(foo(bar))]  //~ ERROR bad macro import
 extern crate std;
diff --git a/src/test/compile-fail/macro-use-bad-args-2.rs b/src/test/compile-fail/macro-use-bad-args-2.rs
index 11a0108b99b..89004f16897 100644
--- a/src/test/compile-fail/macro-use-bad-args-2.rs
+++ b/src/test/compile-fail/macro-use-bad-args-2.rs
@@ -10,5 +10,6 @@
 
 #![no_std]
 
+#[allow(unused_extern_crates)]
 #[macro_use(foo="bar")]  //~ ERROR bad macro import
 extern crate std;
diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs
index 3ae878ed1cb..6c0793ee78f 100644
--- a/src/test/compile-fail/method-call-type-binding.rs
+++ b/src/test/compile-fail/method-call-type-binding.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
+    0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
 }
diff --git a/src/test/compile-fail/move-out-of-array-1.rs b/src/test/compile-fail/move-out-of-array-1.rs
index 148dec02823..796b13538b2 100644
--- a/src/test/compile-fail/move-out-of-array-1.rs
+++ b/src/test/compile-fail/move-out-of-array-1.rs
@@ -24,5 +24,5 @@ fn main() {
 }
 
 fn foo(a: [D; 4], i: usize) -> D {
-    a[i] //~ ERROR cannot move out of type `[D; 4]`
+    a[i] //~ ERROR cannot move out of type `[D; 4]`, a non-copy array
 }
diff --git a/src/test/compile-fail/move-out-of-slice-1.rs b/src/test/compile-fail/move-out-of-slice-1.rs
index f3efc68701e..9ca9e0984e4 100644
--- a/src/test/compile-fail/move-out-of-slice-1.rs
+++ b/src/test/compile-fail/move-out-of-slice-1.rs
@@ -15,7 +15,7 @@ struct A;
 fn main() {
     let a: Box<[A]> = Box::new([A]);
     match a {
-        box [a] => {}, //~ ERROR cannot move out of type `[A]`
+        box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
         _ => {}
     }
 }
diff --git a/src/test/compile-fail/no-std-inject.rs b/src/test/compile-fail/no-std-inject.rs
index f384eafa34b..49064853d21 100644
--- a/src/test/compile-fail/no-std-inject.rs
+++ b/src/test/compile-fail/no-std-inject.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![no_std]
+#![allow(unused_extern_crates)]
 
 extern crate core; //~ ERROR: the name `core` is defined multiple times
 extern crate std;
diff --git a/src/test/compile-fail/placement-expr-unstable.rs b/src/test/compile-fail/placement-expr-unstable.rs
index cc73cbe15fe..35695efe1a9 100644
--- a/src/test/compile-fail/placement-expr-unstable.rs
+++ b/src/test/compile-fail/placement-expr-unstable.rs
@@ -12,8 +12,6 @@
 
 #![feature(placement_in_syntax)]
 
-extern crate core;
-
 fn main() {
     use std::boxed::HEAP; //~ ERROR use of unstable library feature
 
diff --git a/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs b/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs
index 9c985839c4d..46c486c63a3 100644
--- a/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs
+++ b/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs
@@ -12,6 +12,8 @@
 // are treated as rvalues and their lifetime is not bounded to
 // the static scope.
 
+fn id<T>(x: T) -> T { x }
+
 struct Test;
 
 enum MyEnum {
@@ -19,12 +21,14 @@ enum MyEnum {
 }
 
 fn structLifetime<'a>() -> &'a Test {
-  let testValue = &Test; //~ ERROR borrowed value does not live long enough
+  let testValue = &id(Test);
+  //~^ ERROR borrowed value does not live long enough
   testValue
 }
 
 fn variantLifetime<'a>() -> &'a MyEnum {
-  let testValue = &MyEnum::Variant1; //~ ERROR borrowed value does not live long enough
+  let testValue = &id(MyEnum::Variant1);
+  //~^ ERROR borrowed value does not live long enough
   testValue
 }
 
diff --git a/src/test/compile-fail/regions-ret.rs b/src/test/compile-fail/regions-ret.rs
index 61c98d69d80..c7cd3ced98d 100644
--- a/src/test/compile-fail/regions-ret.rs
+++ b/src/test/compile-fail/regions-ret.rs
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 fn f(_x: &isize) -> &isize {
-    return &3; //~ ERROR borrowed value does not live long enough
+    return &id(3); //~ ERROR borrowed value does not live long enough
 }
 
 fn main() {
diff --git a/src/test/compile-fail/regions-var-type-out-of-scope.rs b/src/test/compile-fail/regions-var-type-out-of-scope.rs
index 8955a26de0b..031091c4523 100644
--- a/src/test/compile-fail/regions-var-type-out-of-scope.rs
+++ b/src/test/compile-fail/regions-var-type-out-of-scope.rs
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 fn foo(cond: bool) {
     // Here we will infer a type that uses the
     // region of the if stmt then block:
     let mut x;
 
     if cond {
-        x = &3; //~ ERROR borrowed value does not live long enough
+        x = &id(3); //~ ERROR borrowed value does not live long enough
         assert_eq!(*x, 3);
     }
 }
diff --git a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs
index 87a17c0f19a..6a04a2c3704 100644
--- a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs
+++ b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(unused_extern_crates)]
 extern crate std;
 //~^ ERROR the name `std` is defined multiple times
 
diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs
index 09951348448..a89fd802baf 100644
--- a/src/test/compile-fail/resolve_self_super_hint.rs
+++ b/src/test/compile-fail/resolve_self_super_hint.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 mod a {
     extern crate alloc;
diff --git a/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs b/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs
new file mode 100644
index 00000000000..512fb24a0c2
--- /dev/null
+++ b/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs
@@ -0,0 +1,16 @@
+// 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.
+
+// compile-flags:-Zforce-unstable-if-unmarked
+
+#[unstable] //~ ERROR: stability attributes may not be used
+#[stable] //~ ERROR: stability attributes may not be used
+#[rustc_deprecated] //~ ERROR: stability attributes may not be used
+fn main() { }
diff --git a/src/test/compile-fail/static-reference-to-fn-2.rs b/src/test/compile-fail/static-reference-to-fn-2.rs
index 460154f25d7..8d9f442b81d 100644
--- a/src/test/compile-fail/static-reference-to-fn-2.rs
+++ b/src/test/compile-fail/static-reference-to-fn-2.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 struct StateMachineIter<'a> {
     statefn: &'a StateMachineFunc<'a>
 }
@@ -23,19 +25,19 @@ impl<'a> Iterator for StateMachineIter<'a> {
 }
 
 fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
-    self_.statefn = &(state2 as StateMachineFunc);
+    self_.statefn = &id(state2 as StateMachineFunc);
     //~^ ERROR borrowed value does not live long enough
     return Some("state1");
 }
 
 fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
-    self_.statefn = &(state3 as StateMachineFunc);
+    self_.statefn = &id(state3 as StateMachineFunc);
     //~^ ERROR borrowed value does not live long enough
     return Some("state2");
 }
 
 fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
-    self_.statefn = &(finished as StateMachineFunc);
+    self_.statefn = &id(finished as StateMachineFunc);
     //~^ ERROR borrowed value does not live long enough
     return Some("state3");
 }
@@ -46,7 +48,8 @@ fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> {
 
 fn state_iter() -> StateMachineIter<'static> {
     StateMachineIter {
-        statefn: &(state1 as StateMachineFunc) //~ ERROR borrowed value does not live long enough
+        statefn: &id(state1 as StateMachineFunc)
+        //~^ ERROR borrowed value does not live long enough
     }
 }
 
diff --git a/src/test/compile-fail/static-region-bound.rs b/src/test/compile-fail/static-region-bound.rs
index eca22bfdda0..90ed401659c 100644
--- a/src/test/compile-fail/static-region-bound.rs
+++ b/src/test/compile-fail/static-region-bound.rs
@@ -10,11 +10,13 @@
 
 #![feature(box_syntax)]
 
+fn id<T>(x: T) -> T { x }
+
 fn f<T:'static>(_: T) {}
 
 fn main() {
     let x: Box<_> = box 3;
     f(x);
-    let x = &3; //~ ERROR borrowed value does not live long enough
+    let x = &id(3); //~ ERROR borrowed value does not live long enough
     f(x);
 }
diff --git a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs
index 548a5078a74..42fffe546c2 100644
--- a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
-
-// Test that parentheses form doesn't work in expression paths.
+// Test that parentheses form parses in expression paths.
 
 struct Bar<A,R> {
     f: A, r: R
@@ -21,10 +19,10 @@ impl<A,B> Bar<A,B> {
 }
 
 fn bar() {
-    let b = Box::Bar::<isize,usize>::new(); // OK
+    let b = Bar::<isize, usize>::new(); // OK
 
-    let b = Box::Bar::()::new();
-    //~^ ERROR `::` is not supported before parenthesized generic arguments
+    let b = Bar::(isize, usize)::new(); // OK too (for the parser)
+    //~^ ERROR parenthesized parameters may only be used with a trait
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
index fd6c8ad08d6..5fcde4facbe 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
@@ -16,6 +16,7 @@ struct Bar<A> {
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized parameters may only be used with a trait
+    //~| ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs
index 6416e1cacdc..e20d03478ec 100644
--- a/src/test/compile-fail/unused-attr.rs
+++ b/src/test/compile-fail/unused-attr.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![deny(unused_attributes)]
-#![allow(dead_code, unused_imports)]
+#![allow(dead_code, unused_imports, unused_extern_crates)]
 #![feature(custom_attribute)]
 
 #![foo] //~ ERROR unused attribute
diff --git a/src/test/mir-opt/issue-43457.rs b/src/test/mir-opt/issue-43457.rs
new file mode 100644
index 00000000000..708784df317
--- /dev/null
+++ b/src/test/mir-opt/issue-43457.rs
@@ -0,0 +1,55 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z identify_regions -Z span_free_formats
+// ignore-tidy-linelength
+
+// Regression test for #43457: an `EndRegion` was missing from output
+// because compiler was using a faulty means for region map lookup.
+
+use std::cell::RefCell;
+
+fn rc_refcell_test(r: RefCell<i32>) {
+    r.borrow_mut();
+}
+
+fn main() { }
+
+// END RUST SOURCE
+// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
+//
+// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
+//     let mut _0: ();
+//     scope 1 {
+//         let _2: std::cell::RefCell<i32>;
+//     }
+//     let mut _3: std::cell::RefMut<'17dce, i32>;
+//     let mut _4: &'17dce std::cell::RefCell<i32>;
+//
+//     bb0: {
+//         StorageLive(_2);
+//         _2 = _1;
+//         StorageLive(_4);
+//         _4 = &'17dce _2;
+//         _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
+//     }
+//
+//     bb1: {
+//         drop(_3) -> bb2;
+//     }
+//
+//     bb2: {
+//         StorageDead(_4);
+//         EndRegion('17dce);
+//         _0 = ();
+//         StorageDead(_2);
+//         return;
+//     }
+// }
diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs
index 95c307c5670..cb018ff1bfa 100644
--- a/src/test/parse-fail/type-parameters-in-field-exprs.rs
+++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs
@@ -24,4 +24,6 @@ fn main() {
     //~^ ERROR field expressions may not have generic arguments
     f.x::<>;
     //~^ ERROR field expressions may not have generic arguments
+    f.x::();
+    //~^ ERROR field expressions may not have generic arguments
 }
diff --git a/src/test/run-make/alloc-extern-crates/Makefile b/src/test/run-make/alloc-extern-crates/Makefile
index b8c52378554..7197f4e17e3 100644
--- a/src/test/run-make/alloc-extern-crates/Makefile
+++ b/src/test/run-make/alloc-extern-crates/Makefile
@@ -2,4 +2,4 @@
 
 all:
 	$(RUSTC) fakealloc.rs
-	$(RUSTC) ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
+	$(RUSTC) --crate-type=rlib ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
diff --git a/src/test/run-pass-fulldeps/issue-13560.rs b/src/test/run-pass-fulldeps/issue-13560.rs
index 88be7fe1212..0ceb5ed5e75 100644
--- a/src/test/run-pass-fulldeps/issue-13560.rs
+++ b/src/test/run-pass-fulldeps/issue-13560.rs
@@ -11,7 +11,6 @@
 // aux-build:issue-13560-1.rs
 // aux-build:issue-13560-2.rs
 // aux-build:issue-13560-3.rs
-// ignore-musl
 
 // Regression test for issue #13560, the test itself is all in the dependent
 // libraries. The fail which previously failed to compile is the one numbered 3.
diff --git a/src/test/run-pass-fulldeps/linkage-visibility.rs b/src/test/run-pass-fulldeps/linkage-visibility.rs
index f884bb2098e..9839a2c7041 100644
--- a/src/test/run-pass-fulldeps/linkage-visibility.rs
+++ b/src/test/run-pass-fulldeps/linkage-visibility.rs
@@ -11,7 +11,6 @@
 // aux-build:linkage-visibility.rs
 // ignore-android: FIXME(#10356)
 // ignore-windows: std::dynamic_lib does not work on Windows well
-// ignore-musl
 // ignore-emscripten no dynamic linking
 
 extern crate linkage_visibility as foo;
diff --git a/src/test/run-pass/builtin-clone-unwind.rs b/src/test/run-pass/builtin-clone-unwind.rs
new file mode 100644
index 00000000000..90a41135286
--- /dev/null
+++ b/src/test/run-pass/builtin-clone-unwind.rs
@@ -0,0 +1,65 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that builtin implementations of `Clone` cleanup everything
+// in case of unwinding.
+
+use std::thread;
+use std::rc::Rc;
+
+struct S(Rc<()>);
+
+impl Clone for S {
+    fn clone(&self) -> Self {
+        if Rc::strong_count(&self.0) == 7 {
+            panic!("oops");
+        }
+
+        S(self.0.clone())
+    }
+}
+
+fn main() {
+    let counter = Rc::new(());
+
+    // Unwinding with tuples...
+    let ccounter = counter.clone();
+    let result = std::panic::catch_unwind(move || {
+        let _ = (
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter)
+        ).clone();
+    });
+
+    assert!(result.is_err());
+    assert_eq!(
+        1,
+        Rc::strong_count(&counter)
+    );
+
+    // ... and with arrays.
+    let ccounter = counter.clone();
+    let child = std::panic::catch_unwind(move || {
+        let _ = [
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter.clone()),
+            S(ccounter)
+        ].clone();
+    });
+
+    assert!(result.is_err());
+    assert_eq!(
+        1,
+        Rc::strong_count(&counter)
+    );
+}
diff --git a/src/test/run-pass/builtin-clone.rs b/src/test/run-pass/builtin-clone.rs
new file mode 100644
index 00000000000..95903610931
--- /dev/null
+++ b/src/test/run-pass/builtin-clone.rs
@@ -0,0 +1,54 @@
+// 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 that `Clone` is correctly implemented for builtin types.
+// Also test that cloning an array or a tuple is done right, i.e.
+// each component is cloned.
+
+fn test_clone<T: Clone>(arg: T) {
+    let _ = arg.clone();
+}
+
+fn foo() { }
+
+#[derive(Debug, PartialEq, Eq)]
+struct S(i32);
+
+impl Clone for S {
+    fn clone(&self) -> Self {
+        S(self.0 + 1)
+    }
+}
+
+fn main() {
+    test_clone(foo);
+    test_clone([1; 56]);
+    test_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
+
+    let a = [S(0), S(1), S(2)];
+    let b = [S(1), S(2), S(3)];
+    assert_eq!(b, a.clone());
+
+    let a = (
+        (S(1), S(0)),
+        (
+            (S(0), S(0), S(1)),
+            S(0)
+        )
+    );
+    let b = (
+        (S(2), S(1)),
+        (
+            (S(1), S(1), S(2)),
+            S(1)
+        )
+    );
+    assert_eq!(b, a.clone());
+}
diff --git a/src/test/run-pass/deprecation-in-force-unstable.rs b/src/test/run-pass/deprecation-in-force-unstable.rs
new file mode 100644
index 00000000000..542117eca12
--- /dev/null
+++ b/src/test/run-pass/deprecation-in-force-unstable.rs
@@ -0,0 +1,14 @@
+// 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.
+
+// compile-flags:-Zforce-unstable-if-unmarked
+
+#[deprecated] // should work even with -Zforce-unstable-if-unmarked
+fn main() { }
diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs
index 5ed1295c85c..a8fb11f9c62 100644
--- a/src/test/run-pass/issue-37725.rs
+++ b/src/test/run-pass/issue-37725.rs
@@ -8,7 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
-    s.clone();
+trait Foo {
+    fn foo(&self);
+}
+
+fn foo<'a>(s: &'a mut ()) where &'a mut (): Foo {
+    s.foo();
 }
 fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs b/src/test/run-pass/issue-43205.rs
index fdb010a04f4..0e613ac0727 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs
+++ b/src/test/run-pass/issue-43205.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-    z.push((x,y));
+fn main() {
+   &&[()][0];
+   println!("{:?}", &[(),()][1]);
 }
diff --git a/src/test/compile-fail/feature-gate-rvalue_static_promotion.rs b/src/test/run-pass/issue-43910.rs
index f33d0a71481..d61ce7f4689 100644
--- a/src/test/compile-fail/feature-gate-rvalue_static_promotion.rs
+++ b/src/test/run-pass/issue-43910.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[allow(unused_variables)]
+#![deny(unused_variables)]
+
 fn main() {
-    let x: &'static u32 = &42; //~ error: does not live long enough
-    let y: &'static Option<u32> = &None; //~ error: does not live long enough
+    #[allow(unused_variables)]
+    let x = 12;
 }
diff --git a/src/test/run-pass/issue-43923.rs b/src/test/run-pass/issue-43923.rs
new file mode 100644
index 00000000000..e1992e4fc50
--- /dev/null
+++ b/src/test/run-pass/issue-43923.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.
+
+struct A<T: ?Sized> { ptr: T }
+
+fn foo<T>(x: &A<[T]>) {}
+
+fn main() {
+    let a = foo;
+    let b = A { ptr: [a, a, a] };
+    a(&A { ptr: [()] });
+}
diff --git a/src/test/run-pass/lint-unknown-lints-at-crate-level.rs b/src/test/run-pass/lint-unknown-lints-at-crate-level.rs
new file mode 100644
index 00000000000..1e510c28e78
--- /dev/null
+++ b/src/test/run-pass/lint-unknown-lints-at-crate-level.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.
+
+// compile-flags: -D warnings -D unknown-lints
+
+#![allow(unknown_lints)]
+#![allow(random_lint_name)]
+
+fn main() {}
diff --git a/src/test/run-pass/rvalue-static-promotion.rs b/src/test/run-pass/rvalue-static-promotion.rs
index 30643cfc3eb..e57491930a4 100644
--- a/src/test/run-pass/rvalue-static-promotion.rs
+++ b/src/test/run-pass/rvalue-static-promotion.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rvalue_static_promotion)]
-
 #[allow(unused_variables)]
 fn main() {
     let x: &'static u32 = &42;
diff --git a/src/test/run-pass/union/union-basic.rs b/src/test/run-pass/union/union-basic.rs
index de744520cc6..079f6a6b641 100644
--- a/src/test/run-pass/union/union-basic.rs
+++ b/src/test/run-pass/union/union-basic.rs
@@ -10,10 +10,6 @@
 
 // aux-build:union.rs
 
-// FIXME: This test case makes little-endian assumptions.
-// ignore-s390x
-// ignore-sparc
-
 extern crate union;
 use std::mem::{size_of, align_of, zeroed};
 
@@ -39,7 +35,7 @@ fn local() {
         assert_eq!(w.b, 0);
         w.a = 1;
         assert_eq!(w.a, 1);
-        assert_eq!(w.b, 1);
+        assert_eq!(w.b.to_le(), 1);
     }
 }
 
@@ -60,7 +56,7 @@ fn xcrate() {
         assert_eq!(w.b, 0);
         w.a = 1;
         assert_eq!(w.a, 1);
-        assert_eq!(w.b, 1);
+        assert_eq!(w.b.to_le(), 1);
     }
 }
 
diff --git a/src/test/run-pass/wrong-hashset-issue-42918.rs b/src/test/run-pass/wrong-hashset-issue-42918.rs
new file mode 100644
index 00000000000..5a23adeceb5
--- /dev/null
+++ b/src/test/run-pass/wrong-hashset-issue-42918.rs
@@ -0,0 +1,38 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-flags: -O
+
+use std::collections::HashSet;
+
+#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
+enum MyEnum {
+    E0,
+
+    E1,
+
+    E2,
+    E3,
+    E4,
+
+    E5,
+    E6,
+    E7,
+}
+
+
+fn main() {
+    use MyEnum::*;
+    let s: HashSet<_> = [E4, E1].iter().cloned().collect();
+    let mut v: Vec<_> = s.into_iter().collect();
+    v.sort();
+
+    assert_eq!([E1, E4], &v[..]);
+}
diff --git a/src/test/rustdoc/issue-43869.rs b/src/test/rustdoc/issue-43869.rs
new file mode 100644
index 00000000000..2d18e4be532
--- /dev/null
+++ b/src/test/rustdoc/issue-43869.rs
@@ -0,0 +1,32 @@
+// 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(conservative_impl_trait)]
+
+pub fn g() -> impl Iterator<Item=u8> {
+    Some(1u8).into_iter()
+}
+
+pub fn h() -> (impl Iterator<Item=u8>) {
+    Some(1u8).into_iter()
+}
+
+pub fn i() -> impl Iterator<Item=u8> + 'static {
+    Some(1u8).into_iter()
+}
+
+pub fn j() -> impl Iterator<Item=u8> + Clone {
+    Some(1u8).into_iter()
+}
+
+// @has issue_43869/fn.g.html
+// @has issue_43869/fn.h.html
+// @has issue_43869/fn.i.html
+// @has issue_43869/fn.j.html
diff --git a/src/test/rustdoc/remove-duplicates.rs b/src/test/rustdoc/remove-duplicates.rs
new file mode 100644
index 00000000000..6c4f6d0700a
--- /dev/null
+++ b/src/test/rustdoc/remove-duplicates.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+mod foo {
+    pub use bar::*;
+    pub mod bar {
+        pub trait Foo {
+            fn foo();
+        }
+    }
+}
+
+// @count foo/index.html '//*[@class="trait"]' 1
+pub use foo::bar::*;
+pub use foo::*;
diff --git a/src/test/ui/issue-13483.rs b/src/test/ui/issue-13483.rs
new file mode 100644
index 00000000000..86378043912
--- /dev/null
+++ b/src/test/ui/issue-13483.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.
+
+fn main() {
+    if true {
+    } else if {
+    } else {
+    }
+}
+
+fn foo() {
+    if true {
+    } else if {
+    }
+    bar();
+}
+
+fn bar() {}
diff --git a/src/test/ui/issue-13483.stderr b/src/test/ui/issue-13483.stderr
new file mode 100644
index 00000000000..3446969dfd2
--- /dev/null
+++ b/src/test/ui/issue-13483.stderr
@@ -0,0 +1,14 @@
+error: missing condition for `if` statemement
+  --> $DIR/issue-13483.rs:13:14
+   |
+13 |     } else if {
+   |              ^ expected if condition here
+
+error: missing condition for `if` statemement
+  --> $DIR/issue-13483.rs:20:14
+   |
+20 |     } else if {
+   |              ^ expected if condition here
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr
index 8a55c9989e1..5d143697908 100644
--- a/src/test/ui/issue-41652/issue_41652.stderr
+++ b/src/test/ui/issue-41652/issue_41652.stderr
@@ -5,6 +5,7 @@ error[E0599]: no method named `f` found for type `{integer}` in the current scop
    |           ^
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+   = help: try with `{integer}::f`
 note: candidate #1 is defined in the trait `issue_41652_b::Tr`
   --> $DIR/auxiliary/issue_41652_b.rs:14:5
    |
diff --git a/src/test/ui/issue-44023.rs b/src/test/ui/issue-44023.rs
new file mode 100644
index 00000000000..295d4808289
--- /dev/null
+++ b/src/test/ui/issue-44023.rs
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(non_ascii_idents)]
+
+pub fn main () {}
+
+fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+}
diff --git a/src/test/ui/issue-44023.stderr b/src/test/ui/issue-44023.stderr
new file mode 100644
index 00000000000..a17512ba4ab
--- /dev/null
+++ b/src/test/ui/issue-44023.stderr
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-44023.rs:15:42
+   |
+15 |   fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+   |  __________________________________________^
+16 | | }
+   | |_^ expected isize, found ()
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-44078.rs b/src/test/ui/issue-44078.rs
new file mode 100644
index 00000000000..ef47214f2b3
--- /dev/null
+++ b/src/test/ui/issue-44078.rs
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    "😊"";
+}
diff --git a/src/test/ui/issue-44078.stderr b/src/test/ui/issue-44078.stderr
new file mode 100644
index 00000000000..389f3b2479a
--- /dev/null
+++ b/src/test/ui/issue-44078.stderr
@@ -0,0 +1,10 @@
+error: unterminated double quote string
+  --> $DIR/issue-44078.rs:12:8
+   |
+12 |       "😊"";
+   |  ________^
+13 | | }
+   | |__^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
index 6764c58f4bb..1ee00997997 100644
--- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
+++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
@@ -1,25 +1,10 @@
-error[E0308]: mismatched types
+error[E0623]: lifetime mismatch
   --> $DIR/ex2b-push-no-existing-names.rs:16:12
    |
+15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+   |                    --------      -------- these two types are declared with different lifetimes...
 16 |     x.push(y);
-   |            ^ lifetime mismatch
-   |
-   = note: expected type `Ref<'_, _>`
-              found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the function body at 15:1...
-  --> $DIR/ex2b-push-no-existing-names.rs:15:1
-   |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
-  --> $DIR/ex2b-push-no-existing-names.rs:15:1
-   |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
+   |            ^ ...but data from `y` flows into `x` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr
index 4c878f3c0dc..74a40c87c2f 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr
@@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-2.rs:12:9
    |
 11 | fn foo((v, w): (&u8, &u8), x: &u8) {
-   |                 ---           --- these references are not declared with the same lifetime...
+   |                 ---           --- these two types are declared with different lifetimes...
 12 |     v = x;
    |         ^ ...but data from `x` flows here
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs
index 7bd5ebf805f..51271243bdf 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
-    v = x;
+fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+    z.push((x,y));
 }
 
 fn main() { }
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr
index 08506b8befa..898866c75f2 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr
@@ -1,10 +1,18 @@
 error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-3.rs:12:9
+  --> $DIR/ex3-both-anon-regions-3.rs:12:13
    |
-11 | fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
-   |                 ---                 --- these references are not declared with the same lifetime...
-12 |     v = x;
-   |         ^ ...but data flows here
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                     ---                 --- these two types are declared with different lifetimes...
+12 |     z.push((x,y));
+   |             ^ ...but data flows into `z` here
 
-error: aborting due to previous error
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:12:15
+   |
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                         ---                  --- these two types are declared with different lifetimes...
+12 |     z.push((x,y));
+   |               ^ ...but data flows into `z` here
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr
deleted file mode 100644
index 9c2630fc811..00000000000
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0601]: main function not found
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-4.rs:12:13
-   |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                     ---                 --- these references are not declared with the same lifetime...
-12 |     z.push((x,y));
-   |             ^ ...but data flows into `z` here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-4.rs:12:15
-   |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                         ---                  --- these references are not declared with the same lifetime...
-12 |     z.push((x,y));
-   |               ^ ...but data flows into `z` here
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs
new file mode 100644
index 00000000000..2fbf31aead5
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.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.
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: Ref) {
+    x.b = y.b;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr
new file mode 100644
index 00000000000..26f31defc9e
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
+   |
+15 | fn foo(mut x: Ref, y: Ref) {
+   |               ---     --- these two types are declared with different lifetimes...
+16 |     x.b = y.b;
+   |           ^^^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs
new file mode 100644
index 00000000000..120a7ca74ae
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.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.
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref) {
+    x.a = x.b;
+}
+
+fn main() {}
\ No newline at end of file
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
new file mode 100644
index 00000000000..1b5ac7c7b57
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
+   |
+15 | fn foo(mut x: Ref) {
+   |               ---
+   |               |
+   |               this type was declared with multiple lifetimes...
+16 |     x.a = x.b;
+   |           ^^^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs
new file mode 100644
index 00000000000..67ba8ee532a
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs
@@ -0,0 +1,18 @@
+// 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 Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo(mut x: Vec<Ref>, y: Ref) {
+    x.push(y);
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
new file mode 100644
index 00000000000..6ad795400b3
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
+   |
+14 | fn foo(mut x: Vec<Ref>, y: Ref) {
+   |                   ---      --- these two types are declared with different lifetimes...
+15 |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs
new file mode 100644
index 00000000000..a8b1f53fc98
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.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.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut x: Ref, y: &u32) {
+    y = x.b;
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr
new file mode 100644
index 00000000000..31c7ebf6504
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
+   |
+13 | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ----
+   |               |
+   |               these two types are declared with different lifetimes...
+14 |     y = x.b;
+   |         ^^^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs
new file mode 100644
index 00000000000..4933dbb7e7a
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.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.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut y: Ref, x: &u32) {
+    y.b = x;
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr
new file mode 100644
index 00000000000..d54b526aef9
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
+   |
+13 | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+14 |     y.b = x;
+   |           ^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs
new file mode 100644
index 00000000000..e1594b1a277
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.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.
+
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: &u32) {
+    x.b = y;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr
new file mode 100644
index 00000000000..bb7b9ea6843
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
+   |
+16 | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+17 |     x.b = y;
+   |           ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
new file mode 100644
index 00000000000..0dc257ac092
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.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.
+
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&self, x: &i32) -> &i32 {
+    x
+  }
+}
+
+fn main() { }
+
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
new file mode 100644
index 00000000000..890f9b311e7
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -0,0 +1,23 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
+   |
+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 | |   }
+   | |___^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs
new file mode 100644
index 00000000000..0940ce15d1e
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.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.
+
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+    fn foo<'a>(&self, x: &Foo) -> &Foo {
+        if true { x } else { self }
+    }
+}
+
+fn main() {}
+
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
new file mode 100644
index 00000000000..43f00c32c62
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
@@ -0,0 +1,23 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
+   |
+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 | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs
new file mode 100644
index 00000000000..3a7ba415c0d
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs
@@ -0,0 +1,18 @@
+// 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.
+trait Foo {
+    fn foo<'a>(x: &mut Vec<&u8>, y: &u8);
+}
+impl Foo for () {
+    fn foo(x: &mut Vec<&u8>, y: &u8) {
+        x.push(y);
+    }
+}
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
new file mode 100644
index 00000000000..9591df8e8aa
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
+   |
+14 |     fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                        ---      --- these two types are declared with different lifetimes...
+15 |         x.push(y);
+   |                ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs
index 9ebff511876..be48d07b94e 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs
@@ -1,4 +1,4 @@
-// Copyright 2016 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.
 //
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr
index a183d1fffc0..d3291063859 100644
--- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr
+++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr
@@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions.rs:12:12
    |
 11 | fn foo(x: &mut Vec<&u8>, y: &u8) {
-   |                    ---      --- these references are not declared with the same lifetime...
+   |                    ---      --- these two types are declared with different lifetimes...
 12 |     x.push(y);
    |            ^ ...but data from `y` flows into `x` here
 
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.rs b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
index eeafaab44c6..1c904648f9e 100644
--- a/src/test/ui/lifetimes/borrowck-let-suggestion.rs
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn f() {
-    let x = [1].iter();
+    let x = vec![1].iter();
 }
 
 fn main() {
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
index d1ba9246588..6316c066660 100644
--- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
@@ -1,14 +1,15 @@
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/borrowck-let-suggestion.rs:12:23
+  --> $DIR/borrowck-let-suggestion.rs:12:27
    |
-12 |     let x = [1].iter();
-   |             ---       ^ temporary value dropped here while still borrowed
+12 |     let x = vec![1].iter();
+   |             -------       ^ temporary value dropped here while still borrowed
    |             |
    |             temporary value created here
 13 | }
    | - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime
+   = note: this error originates in a macro outside of the current crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs
index 5aea5f2ca06..c549ded4db2 100644
--- a/src/test/ui/lint/fn_must_use.rs
+++ b/src/test/ui/lint/fn_must_use.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(fn_must_use)]
 #![warn(unused_must_use)]
 
 struct MyStruct {
diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr
index 20eb7452aea..242837793a0 100644
--- a/src/test/ui/lint/fn_must_use.stderr
+++ b/src/test/ui/lint/fn_must_use.stderr
@@ -1,18 +1,18 @@
 warning: unused return value of `need_to_use_this_value` which must be used: it's important
-  --> $DIR/fn_must_use.rs:30:5
+  --> $DIR/fn_must_use.rs:31:5
    |
-30 |     need_to_use_this_value();
+31 |     need_to_use_this_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/fn_must_use.rs:11:9
+  --> $DIR/fn_must_use.rs:12:9
    |
-11 | #![warn(unused_must_use)]
+12 | #![warn(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
 warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
-  --> $DIR/fn_must_use.rs:33:5
+  --> $DIR/fn_must_use.rs:34:5
    |
-33 |     m.need_to_use_this_method_value();
+34 |     m.need_to_use_this_method_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
index 4b32ecff2fb..a401861274d 100644
--- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr
+++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
@@ -6,7 +6,7 @@ error[E0425]: cannot find value `A` in module `namespaced_enums`
    |
 help: possible candidate is found in another module, you can import it into scope
    |
-12 | use namespaced_enums::Foo::A;
+14 | use namespaced_enums::Foo::A;
    |
 
 error[E0425]: cannot find function `B` in module `namespaced_enums`
@@ -17,7 +17,7 @@ error[E0425]: cannot find function `B` in module `namespaced_enums`
    |
 help: possible candidate is found in another module, you can import it into scope
    |
-12 | use namespaced_enums::Foo::B;
+14 | use namespaced_enums::Foo::B;
    |
 
 error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
@@ -28,7 +28,7 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace
    |
 help: possible candidate is found in another module, you can import it into scope
    |
-12 | use namespaced_enums::Foo::C;
+14 | use namespaced_enums::Foo::C;
    |
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr
index f4d183192b6..da849ecc71a 100644
--- a/src/test/ui/resolve/issue-21221-3.stderr
+++ b/src/test/ui/resolve/issue-21221-3.stderr
@@ -6,7 +6,7 @@ error[E0405]: cannot find trait `OuterTrait` in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
    |
-16 | use issue_21221_3::outer::OuterTrait;
+18 | use issue_21221_3::outer::OuterTrait;
    |
 
 error: cannot continue compilation due to previous error
diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr
index eb71ee893ce..78059ed37be 100644
--- a/src/test/ui/resolve/issue-21221-4.stderr
+++ b/src/test/ui/resolve/issue-21221-4.stderr
@@ -6,7 +6,7 @@ error[E0405]: cannot find trait `T` in this scope
    |
 help: possible candidate is found in another module, you can import it into scope
    |
-16 | use issue_21221_4::T;
+18 | use issue_21221_4::T;
    |
 
 error: cannot continue compilation due to previous error
diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr
index 70b4599dbf8..7a4d0ca698e 100644
--- a/src/test/ui/resolve/issue-3907.stderr
+++ b/src/test/ui/resolve/issue-3907.stderr
@@ -6,7 +6,7 @@ error[E0404]: expected trait, found type alias `Foo`
    |
 help: possible better candidate is found in another module, you can import it into scope
    |
-12 | use issue_3907::Foo;
+14 | use issue_3907::Foo;
    |
 
 error: cannot continue compilation due to previous error
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index 47141eda33c..ee1481ec6f2 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
    |
-15 | use m::n::Z;
+16 |     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
    |
-13 | use m::S;
+15 | 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
    |
-13 | use m::S;
+15 | 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
new file mode 100644
index 00000000000..e0027fed4d6
--- /dev/null
+++ b/src/test/ui/resolve/use_suggestion_placement.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.
+
+macro_rules! y {
+    () => {}
+}
+
+mod m {
+    pub const A: i32 = 0;
+}
+
+fn main() {
+    y!();
+    let _ = A;
+    foo();
+}
+
+fn foo() {
+    type Dict<K, V> = HashMap<K, V>;
+}
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
new file mode 100644
index 00000000000..5c74d8bed66
--- /dev/null
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -0,0 +1,38 @@
+error[E0425]: cannot find value `A` in this scope
+  --> $DIR/use_suggestion_placement.rs:21:13
+   |
+21 |     let _ = A;
+   |             ^ not found in this scope
+   |
+help: possible candidate is found in another module, you can import it into scope
+   |
+11 | use m::A;
+   |
+
+error[E0412]: cannot find type `HashMap` in this scope
+  --> $DIR/use_suggestion_placement.rs:26:23
+   |
+26 |     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
+   |
+11 | use std::collections::HashMap;
+   |
+11 | use std::collections::hash_map::HashMap;
+   |
+
+error[E0091]: type parameter `K` is unused
+  --> $DIR/use_suggestion_placement.rs:26:15
+   |
+26 |     type Dict<K, V> = HashMap<K, V>;
+   |               ^ unused type parameter
+
+error[E0091]: type parameter `V` is unused
+  --> $DIR/use_suggestion_placement.rs:26:18
+   |
+26 |     type Dict<K, V> = HashMap<K, V>;
+   |                  ^ unused type parameter
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr
index b2da0c6a296..c33b89953e2 100644
--- a/src/test/ui/span/E0536.stderr
+++ b/src/test/ui/span/E0536.stderr
@@ -2,7 +2,7 @@ error[E0536]: expected 1 cfg-pattern
   --> $DIR/E0536.rs:11:7
    |
 11 | #[cfg(not())] //~ ERROR E0536
-   |       ^^^
+   |       ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr
index 29873943f44..9d66ddbaae3 100644
--- a/src/test/ui/span/E0537.stderr
+++ b/src/test/ui/span/E0537.stderr
@@ -2,7 +2,7 @@ error[E0537]: invalid predicate `unknown`
   --> $DIR/E0537.rs:11:7
    |
 11 | #[cfg(unknown())] //~ ERROR E0537
-   |       ^^^^^^^
+   |       ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
index 1206d716672..9e316b989a4 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 fn f() {
     let old = ['o'];         // statement 0
     let mut v1 = Vec::new(); // statement 1
@@ -21,7 +23,7 @@ fn f() {
 
     let mut v3 = Vec::new(); // statement 5
 
-    v3.push(&'x');           // statement 6
+    v3.push(&id('x'));           // statement 6
     //~^ ERROR borrowed value does not live long enough
     //~| NOTE temporary value created here
     //~| NOTE temporary value only lives until here
@@ -31,7 +33,7 @@ fn f() {
 
         let mut v4 = Vec::new(); // (sub) statement 0
 
-        v4.push(&'y');
+        v4.push(&id('y'));
         //~^ ERROR borrowed value does not live long enough
         //~| NOTE temporary value created here
         //~| NOTE temporary value only lives until here
@@ -42,7 +44,7 @@ fn f() {
 
     let mut v5 = Vec::new(); // statement 8
 
-    v5.push(&'z');
+    v5.push(&id('z'));
     //~^ ERROR borrowed value does not live long enough
     //~| NOTE temporary value created here
     //~| NOTE temporary value only lives until here
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
index 6ed1b7c2622..86c6f28ef1c 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -1,49 +1,49 @@
 error[E0597]: `young[..]` does not live long enough
-  --> $DIR/borrowck-let-suggestion-suffixes.rs:52:1
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:54:1
    |
-19 |     v2.push(&young[0]);      // statement 4
+21 |     v2.push(&young[0]);      // statement 4
    |              -------- borrow occurs here
 ...
-52 | }
+54 | }
    | ^ `young[..]` dropped here while still borrowed
    |
    = note: values in a scope are dropped in the opposite order they are created
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/borrowck-let-suggestion-suffixes.rs:24:18
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:26:22
    |
-24 |     v3.push(&'x');           // statement 6
-   |              --- ^ temporary value dropped here while still borrowed
+26 |     v3.push(&id('x'));           // statement 6
+   |              ------- ^ temporary value dropped here while still borrowed
    |              |
    |              temporary value created here
 ...
-52 | }
+54 | }
    | - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/borrowck-let-suggestion-suffixes.rs:34:22
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:36:26
    |
-34 |         v4.push(&'y');
-   |                  --- ^ temporary value dropped here while still borrowed
+36 |         v4.push(&id('y'));
+   |                  ------- ^ temporary value dropped here while still borrowed
    |                  |
    |                  temporary value created here
 ...
-40 |     }                       // (statement 7)
+42 |     }                       // (statement 7)
    |     - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/borrowck-let-suggestion-suffixes.rs:45:18
+  --> $DIR/borrowck-let-suggestion-suffixes.rs:47:22
    |
-45 |     v5.push(&'z');
-   |              --- ^ temporary value dropped here while still borrowed
+47 |     v5.push(&id('z'));
+   |              ------- ^ temporary value dropped here while still borrowed
    |              |
    |              temporary value created here
 ...
-52 | }
+54 | }
    | - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime
diff --git a/src/test/ui/span/import-ty-params.rs b/src/test/ui/span/import-ty-params.rs
index d1e3d20f4ba..793ea68beba 100644
--- a/src/test/ui/span/import-ty-params.rs
+++ b/src/test/ui/span/import-ty-params.rs
@@ -21,10 +21,10 @@ macro_rules! import {
 }
 
 fn f1() {
-    import! { a::b::c::S<u8> } //~ ERROR generic arguments in import path
+    import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path
 }
 fn f2() {
-    import! { a::b::c::S<> } //~ ERROR generic arguments in import path
+    import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path
 }
 
 fn main() {}
diff --git a/src/test/ui/span/import-ty-params.stderr b/src/test/ui/span/import-ty-params.stderr
index de959a14cc5..e2c3e34c471 100644
--- a/src/test/ui/span/import-ty-params.stderr
+++ b/src/test/ui/span/import-ty-params.stderr
@@ -1,14 +1,14 @@
-error: generic arguments in import path
-  --> $DIR/import-ty-params.rs:24:25
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:24:15
    |
-24 |     import! { a::b::c::S<u8> } //~ ERROR generic arguments in import path
-   |                         ^^^^
+24 |     import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path
+   |               ^^^^^^^^^^^^^^
 
-error: generic arguments in import path
-  --> $DIR/import-ty-params.rs:27:25
+error: unexpected generic arguments in path
+  --> $DIR/import-ty-params.rs:27:15
    |
-27 |     import! { a::b::c::S<> } //~ ERROR generic arguments in import path
-   |                         ^^
+27 |     import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path
+   |               ^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-15480.rs b/src/test/ui/span/issue-15480.rs
index ea5f4d3fe60..871e0af50bf 100644
--- a/src/test/ui/span/issue-15480.rs
+++ b/src/test/ui/span/issue-15480.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+fn id<T>(x: T) -> T { x }
+
 fn main() {
     let v = vec![
-        &3
+        &id(3)
     ];
 
     for &&x in &v {
diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr
index ce1c6e81b96..7f4ca19241c 100644
--- a/src/test/ui/span/issue-15480.stderr
+++ b/src/test/ui/span/issue-15480.stderr
@@ -1,12 +1,12 @@
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/issue-15480.rs:14:6
+  --> $DIR/issue-15480.rs:16:6
    |
-13 |         &3
-   |          - temporary value created here
-14 |     ];
+15 |         &id(3)
+   |          ----- temporary value created here
+16 |     ];
    |      ^ temporary value dropped here while still borrowed
 ...
-19 | }
+21 | }
    | - temporary value needs to live until here
    |
    = note: consider using a `let` binding to increase its lifetime
diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr
index 4f1c870d874..d4c0eb21342 100644
--- a/src/test/ui/span/issue-24690.stderr
+++ b/src/test/ui/span/issue-24690.stderr
@@ -10,6 +10,7 @@ note: lint level defined here
 18 | #![warn(unused)]
    |         ^^^^^^
    = note: #[warn(unused_variables)] implied by #[warn(unused)]
+   = note: to disable this warning, consider using `_theOtherTwo` instead
 
 warning: variable `theTwo` should have a snake case name such as `the_two`
   --> $DIR/issue-24690.rs:22:9
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index ff62adbfbd5..08ec2a87fcd 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -5,6 +5,7 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope
    |                  ^^
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+   = help: try with `usize::f9`
 note: candidate #1 is defined in the trait `CtxtFn`
   --> $DIR/issue-7575.rs:16:5
    |
@@ -36,6 +37,7 @@ error[E0599]: no method named `fff` found for type `Myisize` in the current scop
    |                              ^^^
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+   = help: try with `Myisize::fff`
 note: candidate #1 is defined in an impl for the type `Myisize`
   --> $DIR/issue-7575.rs:51:5
    |
@@ -51,6 +53,7 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope
    |       ^^^^^^
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+   = help: try with `T::is_str`
 note: candidate #1 is defined in the trait `ManyImplTrait`
   --> $DIR/issue-7575.rs:57:5
    |
diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs
index 08a7518dff9..c2443b024ce 100644
--- a/src/test/ui/span/macro-ty-params.rs
+++ b/src/test/ui/span/macro-ty-params.rs
@@ -16,16 +16,6 @@ macro_rules! m {
 
 fn main() {
     foo::<T>!();
-    //~^ ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
     foo::<>!();
-    //~^ ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
     m!(MyTrait<>);
-    //~^ ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
-    //~| ERROR generic arguments in macro path
 }
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index f7115a04826..1d2f7bb2f07 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -1,3 +1,15 @@
+error: unexpected generic arguments in path
+  --> $DIR/macro-ty-params.rs:20:8
+   |
+20 |     m!(MyTrait<>);
+   |        ^^^^^^^^^
+
+error: unexpected generic arguments in path
+  --> $DIR/macro-ty-params.rs:20:8
+   |
+20 |     m!(MyTrait<>);
+   |        ^^^^^^^^^
+
 error: generic arguments in macro path
   --> $DIR/macro-ty-params.rs:18:8
    |
@@ -5,16 +17,16 @@ error: generic arguments in macro path
    |        ^^^^^
 
 error: generic arguments in macro path
-  --> $DIR/macro-ty-params.rs:22:8
+  --> $DIR/macro-ty-params.rs:19:8
    |
-22 |     foo::<>!();
+19 |     foo::<>!();
    |        ^^^^
 
 error: generic arguments in macro path
-  --> $DIR/macro-ty-params.rs:26:15
+  --> $DIR/macro-ty-params.rs:20:15
    |
-26 |     m!(MyTrait<>);
+20 |     m!(MyTrait<>);
    |               ^^
 
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs
index a524562f2d9..99b0d6ed296 100644
--- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs
@@ -10,6 +10,8 @@
 
 #![feature(box_syntax)]
 
+fn id<T>(x: T) -> T { x }
+
 trait Foo { }
 
 impl<'a> Foo for &'a isize { }
@@ -17,7 +19,7 @@ impl<'a> Foo for &'a isize { }
 fn main() {
     let blah;
     {
-        let ss: &isize = &1;
+        let ss: &isize = &id(1);
         blah = box ss as Box<Foo>;
     }
 }
diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
index e671f1daf61..6a3625441b4 100644
--- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
+++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr
@@ -1,12 +1,12 @@
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:22:5
+  --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:24:5
    |
-20 |         let ss: &isize = &1;
-   |                           - temporary value created here
-21 |         blah = box ss as Box<Foo>;
-22 |     }
+22 |         let ss: &isize = &id(1);
+   |                           ----- temporary value created here
+23 |         blah = box ss as Box<Foo>;
+24 |     }
    |     ^ temporary value dropped here while still borrowed
-23 | }
+25 | }
    | - temporary value needs to live until here
 
 error: aborting due to previous error
diff --git a/src/test/ui/span/slice-borrow.rs b/src/test/ui/span/slice-borrow.rs
index 4ca0ccaa731..1b022f23246 100644
--- a/src/test/ui/span/slice-borrow.rs
+++ b/src/test/ui/span/slice-borrow.rs
@@ -13,7 +13,7 @@
 fn main() {
     let y;
     {
-        let x: &[isize] = &[1, 2, 3, 4, 5];
+        let x: &[isize] = &vec![1, 2, 3, 4, 5];
         y = &x[1..];
     }
 }
diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr
index b60ccd0fbf3..5e8edf80df6 100644
--- a/src/test/ui/span/slice-borrow.stderr
+++ b/src/test/ui/span/slice-borrow.stderr
@@ -1,13 +1,15 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/slice-borrow.rs:18:5
    |
-16 |         let x: &[isize] = &[1, 2, 3, 4, 5];
-   |                            --------------- temporary value created here
+16 |         let x: &[isize] = &vec![1, 2, 3, 4, 5];
+   |                            ------------------- temporary value created here
 17 |         y = &x[1..];
 18 |     }
    |     ^ temporary value dropped here while still borrowed
 19 | }
    | - temporary value needs to live until here
+   |
+   = note: this error originates in a macro outside of the current crate
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/visibility-ty-params.rs b/src/test/ui/span/visibility-ty-params.rs
index 8d4817e80b9..2a4a5edd04c 100644
--- a/src/test/ui/span/visibility-ty-params.rs
+++ b/src/test/ui/span/visibility-ty-params.rs
@@ -13,11 +13,11 @@ macro_rules! m {
 }
 
 struct S<T>(T);
-m!{ S<u8> } //~ ERROR generic arguments in visibility path
+m!{ S<u8> } //~ ERROR unexpected generic arguments in path
 //~^ ERROR expected module, found struct `S`
 
 mod m {
-    m!{ m<> } //~ ERROR generic arguments in visibility path
+    m!{ m<> } //~ ERROR unexpected generic arguments in path
 }
 
 fn main() {}
diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr
index 0460b7ca025..673b9a38e03 100644
--- a/src/test/ui/span/visibility-ty-params.stderr
+++ b/src/test/ui/span/visibility-ty-params.stderr
@@ -1,22 +1,14 @@
-error[E0577]: expected module, found struct `S`
+error: unexpected generic arguments in path
   --> $DIR/visibility-ty-params.rs:16:5
    |
-16 | m!{ S<u8> } //~ ERROR generic arguments in visibility path
-   |     -^^^^
-   |     |
-   |     did you mean `m`?
+16 | m!{ S<u8> } //~ ERROR unexpected generic arguments in path
+   |     ^^^^^
 
-error: generic arguments in visibility path
-  --> $DIR/visibility-ty-params.rs:16:6
+error: unexpected generic arguments in path
+  --> $DIR/visibility-ty-params.rs:20:9
    |
-16 | m!{ S<u8> } //~ ERROR generic arguments in visibility path
-   |      ^^^^
+20 |     m!{ m<> } //~ ERROR unexpected generic arguments in path
+   |         ^^^
 
-error: generic arguments in visibility path
-  --> $DIR/visibility-ty-params.rs:20:10
-   |
-20 |     m!{ m<> } //~ ERROR generic arguments in visibility path
-   |          ^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/union-sized-field.rs b/src/test/ui/union-sized-field.rs
new file mode 100644
index 00000000000..eeca5ab7404
--- /dev/null
+++ b/src/test/ui/union-sized-field.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(untagged_unions)]
+
+union Foo<T: ?Sized> {
+    value: T,
+}
+
+struct Foo2<T: ?Sized> {
+    value: T,
+    t: u32,
+}
+
+enum Foo3<T: ?Sized> {
+    Value(T),
+}
+
+fn main() {}
diff --git a/src/test/ui/union-sized-field.stderr b/src/test/ui/union-sized-field.stderr
new file mode 100644
index 00000000000..ea90d97c4c3
--- /dev/null
+++ b/src/test/ui/union-sized-field.stderr
@@ -0,0 +1,32 @@
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:14:5
+   |
+14 |     value: T,
+   |     ^^^^^^^^ `T` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: no field of a union may have a dynamically sized type
+
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:18:5
+   |
+18 |     value: T,
+   |     ^^^^^^^^ `T` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: only the last field of a struct may have a dynamically sized type
+
+error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
+  --> $DIR/union-sized-field.rs:23:11
+   |
+23 |     Value(T),
+   |           ^^ `T` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `T`
+   = help: consider adding a `where T: std::marker::Sized` bound
+   = note: no field of an enum variant may have a dynamically sized type
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index b8efb88acfb..7a09ae48b91 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -94,6 +94,7 @@ static TARGETS: &'static [&'static str] = &[
     "x86_64-unknown-linux-gnu",
     "x86_64-unknown-linux-musl",
     "x86_64-unknown-netbsd",
+    "x86_64-unknown-redox",
 ];
 
 static MINGW: &'static [&'static str] = &[
@@ -181,15 +182,15 @@ fn main() {
     t!(io::stdin().read_to_string(&mut passphrase));
 
     Builder {
-        rust_release: rust_release,
-        cargo_release: cargo_release,
-        rls_release: rls_release,
-        input: input,
-        output: output,
+        rust_release,
+        cargo_release,
+        rls_release,
+        input,
+        output,
         gpg_passphrase: passphrase,
         digests: BTreeMap::new(),
-        s3_address: s3_address,
-        date: date,
+        s3_address,
+        date,
         rust_version: String::new(),
         cargo_version: String::new(),
         rls_version: String::new(),
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7704f7b1fd52607104cc7fdc435d636c9de1fe9
+Subproject 3d3f2c05d742e5f907e951aa8849b03f0bc1a89
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 0b9b9599be6..b7fb3670165 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -175,8 +175,8 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
            msg);
     Some((which,
           Error {
-        line_num: line_num,
-        kind: kind,
-        msg: msg,
+        line_num,
+        kind,
+        msg,
     }))
 }
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 23782c3ccc9..77ee93c3007 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -148,8 +148,8 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
             let kind = ErrorKind::from_str(&diagnostic.level).ok();
             expected_errors.push(Error {
                 line_num: span.line_start,
-                kind: kind,
-                msg: msg,
+                kind,
+                msg,
             });
         }
     }
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 6fa758aeabe..15216f52d91 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -14,6 +14,7 @@
 
 #![deny(warnings)]
 
+#[cfg(any(target_os = "macos", target_os = "ios"))]
 extern crate libc;
 extern crate test;
 extern crate getopts;
@@ -39,7 +40,6 @@ use util::logv;
 
 use self::header::EarlyProps;
 
-pub mod procsrv;
 pub mod util;
 mod json;
 pub mod header;
@@ -176,9 +176,9 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         target_rustcflags: matches.opt_str("target-rustcflags"),
         target: opt_str2(matches.opt_str("target")),
         host: opt_str2(matches.opt_str("host")),
-        gdb: gdb,
-        gdb_version: gdb_version,
-        gdb_native_rust: gdb_native_rust,
+        gdb,
+        gdb_version,
+        gdb_native_rust,
         lldb_version: extract_lldb_version(matches.opt_str("lldb-version")),
         llvm_version: matches.opt_str("llvm-version"),
         system_llvm: matches.opt_present("system-llvm"),
@@ -192,7 +192,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         lldb_python_dir: matches.opt_str("lldb-python-dir"),
         verbose: matches.opt_present("verbose"),
         quiet: matches.opt_present("quiet"),
-        color: color,
+        color,
         remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
 
         cc: matches.opt_str("cc").unwrap(),
@@ -470,8 +470,8 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     test::TestDescAndFn {
         desc: test::TestDesc {
             name: make_test_name(config, testpaths),
-            ignore: ignore,
-            should_panic: should_panic,
+            ignore,
+            should_panic,
             allow_fail: false,
         },
         testfn: make_test_closure(config, testpaths),
diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs
deleted file mode 100644
index b6d89c1f51a..00000000000
--- a/src/tools/compiletest/src/procsrv.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::env;
-use std::ffi::OsString;
-use std::io::prelude::*;
-use std::io;
-use std::path::PathBuf;
-use std::process::{Child, Command, ExitStatus, Output, Stdio};
-
-/// Get the name of the environment variable that holds dynamic library
-/// locations
-pub fn dylib_env_var() -> &'static str {
-    if cfg!(windows) {
-        "PATH"
-    } else if cfg!(target_os = "macos") {
-        "DYLD_LIBRARY_PATH"
-    } else if cfg!(target_os = "haiku") {
-        "LIBRARY_PATH"
-    } else {
-        "LD_LIBRARY_PATH"
-    }
-}
-
-/// Add `lib_path` and `aux_path` (if it is `Some`) to the dynamic library
-/// env var
-fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
-    // Need to be sure to put both the lib_path and the aux path in the dylib
-    // search path for the child.
-    let var = dylib_env_var();
-    let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
-        .collect::<Vec<_>>();
-    if let Some(p) = aux_path {
-        path.insert(0, PathBuf::from(p))
-    }
-    path.insert(0, PathBuf::from(lib_path));
-
-    // Add the new dylib search path var
-    let newpath = env::join_paths(&path).unwrap();
-    cmd.env(var, newpath);
-}
-
-/// Represents exit status, stdout and stderr of a completed process
-pub struct Result {
-    pub status: ExitStatus,
-    pub out: String,
-    pub err: String,
-}
-
-/// Runs a test program
-///
-/// # Params
-///  - `lib_path` Path to search for required library
-///  - `prog` command to run
-///  - `aux_path` Optional extra path to search for required
-///    auxiliary libraries
-///  - `args` List of arguments to pass to `prog`
-///  - `env` List of environment variables to set, `.0` is variable name,
-///    `.1` is value
-///  - `input` String to be fed as stdin
-///  - `current_dir` Optional working dir to run command in
-///
-pub fn run(lib_path: &str,
-           prog: &str,
-           aux_path: Option<&str>,
-           args: &[String],
-           env: Vec<(String, String)>,
-           input: Option<String>,
-           current_dir: Option<String>)
-           -> io::Result<Result> {
-
-    let mut cmd = Command::new(prog);
-    cmd.args(args)
-        .stdout(Stdio::piped())
-        .stderr(Stdio::piped())
-        .stdin(Stdio::piped());
-
-    add_target_env(&mut cmd, lib_path, aux_path);
-    for (key, val) in env {
-        cmd.env(&key, &val);
-    }
-    if let Some(cwd) = current_dir {
-        cmd.current_dir(cwd);
-    }
-
-    let mut process = cmd.spawn()?;
-    if let Some(input) = input {
-        process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
-    }
-    let Output { status, stdout, stderr } = process.wait_with_output().unwrap();
-
-    Ok(Result {
-        status: status,
-        out: String::from_utf8(stdout).unwrap(),
-        err: String::from_utf8(stderr).unwrap(),
-    })
-}
-
-/// Same as `run`, but return process rather than waiting on completion
-pub fn run_background(lib_path: &str,
-                      prog: &str,
-                      aux_path: Option<&str>,
-                      args: &[String],
-                      env: Vec<(String, String)>,
-                      input: Option<String>,
-                      current_dir: Option<String>)
-                      -> io::Result<Child> {
-
-    let mut cmd = Command::new(prog);
-    cmd.args(args)
-       .stdin(Stdio::piped())
-       .stdout(Stdio::piped());
-    add_target_env(&mut cmd, lib_path, aux_path);
-    for (key, val) in env {
-        cmd.env(&key, &val);
-    }
-    if let Some(cwd) = current_dir {
-        cmd.current_dir(cwd);
-    }
-
-    let mut process = cmd.spawn()?;
-    if let Some(input) = input {
-        process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
-    }
-
-    Ok(process)
-}
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 769748c63c0..d2a0c776b33 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -17,22 +17,35 @@ use errors::{self, ErrorKind, Error};
 use filetime::FileTime;
 use json;
 use header::TestProps;
-use procsrv;
 use test::TestPaths;
 use util::logv;
 
+use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
+use std::ffi::OsString;
 use std::fs::{self, File, create_dir_all};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output, ExitStatus};
+use std::process::{Command, Output, ExitStatus, Stdio};
 use std::str;
-use std::collections::HashMap;
 
 use extract_gdb_version;
 
+/// The name of the environment variable that holds dynamic library locations.
+pub fn dylib_env_var() -> &'static str {
+    if cfg!(windows) {
+        "PATH"
+    } else if cfg!(target_os = "macos") {
+        "DYLD_LIBRARY_PATH"
+    } else if cfg!(target_os = "haiku") {
+        "LIBRARY_PATH"
+    } else {
+        "LD_LIBRARY_PATH"
+    }
+}
+
 pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
 
@@ -59,7 +72,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
 
     let base_cx = TestCx { config: &config,
                            props: &base_props,
-                           testpaths: testpaths,
+                           testpaths,
                            revision: None };
     base_cx.init_all();
 
@@ -72,7 +85,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
             let rev_cx = TestCx {
                 config: &config,
                 props: &revision_props,
-                testpaths: testpaths,
+                testpaths,
                 revision: Some(revision)
             };
             rev_cx.run_revision();
@@ -325,37 +338,23 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn print_source(&self,
-                    src: String,
-                    pretty_type: &str)
-                    -> ProcRes {
+    fn print_source(&self, src: String, pretty_type: &str) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
-        self.compose_and_run(self.make_pp_args(pretty_type.to_owned()),
-                             self.props.exec_env.clone(),
+
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc.arg("-")
+            .arg("-Zunstable-options")
+            .args(&["--unpretty", &pretty_type])
+            .args(&["--target", &self.config.target])
+            .arg("-L").arg(&aux_dir)
+            .args(self.split_maybe_args(&self.config.target_rustcflags))
+            .args(&self.props.compile_flags)
+            .envs(self.props.exec_env.clone());
+
+        self.compose_and_run(rustc,
                              self.config.compile_lib_path.to_str().unwrap(),
                              Some(aux_dir.to_str().unwrap()),
-                             Some(src),
-                             None)
-    }
-
-    fn make_pp_args(&self,
-                    pretty_type: String)
-                    -> ProcArgs {
-        let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec!["-".to_owned(),
-                            "-Zunstable-options".to_owned(),
-                            "--unpretty".to_owned(),
-                            pretty_type,
-                            format!("--target={}", self.config.target),
-                            "-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned()];
-        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        args.extend(self.props.compile_flags.iter().cloned());
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args: args,
-        }
+                             Some(src))
     }
 
     fn compare_source(&self,
@@ -379,45 +378,35 @@ actual:\n\
     }
 
     fn typecheck_source(&self, src: String) -> ProcRes {
-        let args = self.make_typecheck_args();
-        self.compose_and_run_compiler(args, Some(src))
-    }
+        let mut rustc = Command::new(&self.config.rustc_path);
+
+        let out_dir = self.output_base_name().with_extension("pretty-out");
+        let _ = fs::remove_dir_all(&out_dir);
+        create_dir_all(&out_dir).unwrap();
 
-    fn make_typecheck_args(&self) -> ProcArgs {
-        let aux_dir = self.aux_output_dir_name();
         let target = if self.props.force_host {
             &*self.config.host
         } else {
             &*self.config.target
         };
 
-        let out_dir = self.output_base_name().with_extension("pretty-out");
-        let _ = fs::remove_dir_all(&out_dir);
-        create_dir_all(&out_dir).unwrap();
+        let aux_dir = self.aux_output_dir_name();
+
+        rustc.arg("-")
+            .arg("-Zno-trans")
+            .arg("--out-dir").arg(&out_dir)
+            .arg(&format!("--target={}", target))
+            .arg("-L").arg(&self.config.build_base)
+            .arg("-L").arg(aux_dir);
 
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec!["-".to_owned(),
-                            "-Zno-trans".to_owned(),
-                            "--out-dir".to_owned(),
-                            out_dir.to_str().unwrap().to_owned(),
-                            format!("--target={}", target),
-                            "-L".to_owned(),
-                            self.config.build_base.to_str().unwrap().to_owned(),
-                            "-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned()];
         if let Some(revision) = self.revision {
-            args.extend(vec![
-                "--cfg".to_string(),
-                revision.to_string(),
-            ]);
-        }
-        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        args.extend(self.props.compile_flags.iter().cloned());
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args: args,
+            rustc.args(&["--cfg", revision]);
         }
+
+        rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
+        rustc.args(&self.props.compile_flags);
+
+        self.compose_and_run_compiler(rustc, Some(src))
     }
 
     fn run_debuginfo_gdb_test(&self) {
@@ -500,32 +489,19 @@ actual:\n\
                 debug!("script_str = {}", script_str);
                 self.dump_output_file(&script_str, "debugger.script");
 
+                let adb_path = &self.config.adb_path;
 
-                procsrv::run("",
-                             &self.config.adb_path,
-                             None,
-                             &[
-                                 "push".to_owned(),
-                                 exe_file.to_str().unwrap().to_owned(),
-                                 self.config.adb_test_dir.clone()
-                             ],
-                             Vec::new(),
-                             None,
-                             None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
-
-                procsrv::run("",
-                             &self.config.adb_path,
-                             None,
-                             &[
-                                 "forward".to_owned(),
-                                 "tcp:5039".to_owned(),
-                                 "tcp:5039".to_owned()
-                             ],
-                             Vec::new(),
-                             None,
-                             None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+                Command::new(adb_path)
+                    .arg("push")
+                    .arg(&exe_file)
+                    .arg(&self.config.adb_test_dir)
+                    .status()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
+
+                Command::new(adb_path)
+                    .args(&["forward", "tcp:5039", "tcp:5039"])
+                    .status()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
 
                 let adb_arg = format!("export LD_LIBRARY_PATH={}; \
                                        gdbserver{} :5039 {}/{}",
@@ -537,23 +513,17 @@ actual:\n\
                                       .unwrap());
 
                 debug!("adb arg: {}", adb_arg);
-                let mut process = procsrv::run_background("",
-                                                          &self.config.adb_path
-                                                          ,
-                                                          None,
-                                                          &[
-                                                              "shell".to_owned(),
-                                                              adb_arg.clone()
-                                                          ],
-                                                          Vec::new(),
-                                                          None,
-                                                          None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+                let mut adb = Command::new(adb_path)
+                    .args(&["shell", &adb_arg])
+                    .stdout(Stdio::piped())
+                    .stderr(Stdio::inherit())
+                    .spawn()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
 
                 // Wait for the gdbserver to print out "Listening on port ..."
                 // at which point we know that it's started and then we can
                 // execute the debugger below.
-                let mut stdout = BufReader::new(process.stdout.take().unwrap());
+                let mut stdout = BufReader::new(adb.stdout.take().unwrap());
                 let mut line = String::new();
                 loop {
                     line.truncate(0);
@@ -574,33 +544,29 @@ actual:\n\
 
                 let mut gdb_path = tool_path;
                 gdb_path.push_str("/bin/gdb");
-                let procsrv::Result {
-                    out,
-                    err,
-                    status
-                } = procsrv::run("",
-                                 &gdb_path,
-                                 None,
-                                 &debugger_opts,
-                                 Vec::new(),
-                                 None,
-                                 None)
+                let Output {
+                    status,
+                    stdout,
+                    stderr
+                } = Command::new(&gdb_path)
+                    .args(&debugger_opts)
+                    .output()
                     .expect(&format!("failed to exec `{:?}`", gdb_path));
                 let cmdline = {
-                    let cmdline = self.make_cmdline("",
-                                                    &format!("{}-gdb", self.config.target),
-                                                    &debugger_opts);
+                    let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
+                    gdb.args(&debugger_opts);
+                    let cmdline = self.make_cmdline(&gdb, "");
                     logv(self.config, format!("executing {}", cmdline));
                     cmdline
                 };
 
                 debugger_run_result = ProcRes {
-                    status: status,
-                    stdout: out,
-                    stderr: err,
-                    cmdline: cmdline
+                    status,
+                    stdout: String::from_utf8(stdout).unwrap(),
+                    stderr: String::from_utf8(stderr).unwrap(),
+                    cmdline,
                 };
-                if process.kill().is_err() {
+                if adb.kill().is_err() {
                     println!("Adb process is already finished.");
                 }
             }
@@ -679,19 +645,14 @@ actual:\n\
                          "-nx".to_owned(),
                          format!("-command={}", debugger_script.to_str().unwrap())];
 
-                let proc_args = ProcArgs {
-                    prog: self.config.gdb.as_ref().unwrap().to_owned(),
-                    args: debugger_opts,
-                };
-
-                let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];
+                let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
+                gdb.args(&debugger_opts)
+                    .env("PYTHONPATH", rust_pp_module_abs_path);
 
                 debugger_run_result =
-                    self.compose_and_run(proc_args,
-                                         environment,
+                    self.compose_and_run(gdb,
                                          self.config.run_lib_path.to_str().unwrap(),
                                          None,
-                                         None,
                                          None);
             }
         }
@@ -852,7 +813,7 @@ actual:\n\
 
         self.dump_output(&out, &err);
         ProcRes {
-            status: status,
+            status,
             stdout: out,
             stderr: err,
             cmdline: format!("{:?}", cmd)
@@ -899,9 +860,9 @@ actual:\n\
         }
 
         DebuggerCommands {
-            commands: commands,
-            check_lines: check_lines,
-            breakpoint_lines: breakpoint_lines,
+            commands,
+            check_lines,
+            breakpoint_lines,
         }
     }
 
@@ -1154,10 +1115,11 @@ actual:\n\
     }
 
     fn compile_test(&self) -> ProcRes {
-        let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut extra_args = vec!["-L".to_owned(),
-                                  aux_dir.to_str().unwrap().to_owned()];
+        let mut rustc = self.make_compile_args(
+            &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name()));
+
+        rustc.arg("-L").arg(&self.aux_output_dir_name());
+
         match self.config.mode {
             CompileFail | Ui => {
                 // compile-fail and ui tests tend to have tons of unused code as
@@ -1165,15 +1127,12 @@ actual:\n\
                 // want to actually assert warnings about all this code. Instead
                 // let's just ignore unused code warnings by defaults and tests
                 // can turn it back on if needed.
-                extra_args.push("-A".to_owned());
-                extra_args.push("unused".to_owned());
+                rustc.args(&["-A", "unused"]);
             }
             _ => {}
         }
-        let args = self.make_compile_args(extra_args,
-                                          &self.testpaths.file,
-                                          TargetLocation::ThisFile(self.make_exe_name()));
-        self.compose_and_run_compiler(args, None)
+
+        self.compose_and_run_compiler(rustc, None)
     }
 
     fn document(&self, out_dir: &Path) -> ProcRes {
@@ -1197,22 +1156,20 @@ actual:\n\
         }
 
         let aux_dir = self.aux_output_dir_name();
-        let mut args = vec!["-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned(),
-                            "-o".to_owned(),
-                            out_dir.to_str().unwrap().to_owned(),
-                            self.testpaths.file.to_str().unwrap().to_owned()];
-        args.extend(self.props.compile_flags.iter().cloned());
-        let args = ProcArgs {
-            prog: self.config.rustdoc_path
-                .as_ref().expect("--rustdoc-path passed").to_str().unwrap().to_owned(),
-            args: args,
-        };
-        self.compose_and_run_compiler(args, None)
+
+        let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed");
+        let mut rustdoc = Command::new(rustdoc_path);
+
+        rustdoc.arg("-L").arg(aux_dir)
+            .arg("-o").arg(out_dir)
+            .arg(&self.testpaths.file)
+            .args(&self.props.compile_flags);
+
+        self.compose_and_run_compiler(rustdoc, None)
     }
 
     fn exec_compiled_test(&self) -> ProcRes {
-        let env = self.props.exec_env.clone();
+        let env = &self.props.exec_env;
 
         match &*self.config.target {
             // This is pretty similar to below, we're transforming:
@@ -1230,41 +1187,39 @@ actual:\n\
             // the process) and then report back the same result.
             _ if self.config.remote_test_client.is_some() => {
                 let aux_dir = self.aux_output_dir_name();
-                let mut args = self.make_run_args();
-                let mut program = args.prog.clone();
+                let ProcArgs { mut prog, args } = self.make_run_args();
                 if let Ok(entries) = aux_dir.read_dir() {
                     for entry in entries {
                         let entry = entry.unwrap();
                         if !entry.path().is_file() {
                             continue
                         }
-                        program.push_str(":");
-                        program.push_str(entry.path().to_str().unwrap());
+                        prog.push_str(":");
+                        prog.push_str(entry.path().to_str().unwrap());
                     }
                 }
-                args.args.insert(0, program);
-                args.args.insert(0, "run".to_string());
-                args.prog = self.config.remote_test_client.clone().unwrap()
-                                .into_os_string().into_string().unwrap();
-                self.compose_and_run(args,
-                                     env,
+                let mut test_client = Command::new(
+                    self.config.remote_test_client.as_ref().unwrap());
+                test_client
+                    .args(&["run", &prog])
+                    .args(args)
+                    .envs(env.clone());
+                self.compose_and_run(test_client,
                                      self.config.run_lib_path.to_str().unwrap(),
                                      Some(aux_dir.to_str().unwrap()),
-                                     None,
                                      None)
             }
             _ => {
                 let aux_dir = self.aux_output_dir_name();
-                let working_dir =
-                    Some(self.output_base_name()
-                             .parent().unwrap()
-                             .to_str().unwrap().to_owned());
-                self.compose_and_run(self.make_run_args(),
-                                     env,
+                let ProcArgs { prog, args } = self.make_run_args();
+                let mut program = Command::new(&prog);
+                program.args(args)
+                    .current_dir(&self.output_base_name().parent().unwrap())
+                    .envs(env.clone());
+                self.compose_and_run(program,
                                      self.config.run_lib_path.to_str().unwrap(),
                                      Some(aux_dir.to_str().unwrap()),
-                                     None,
-                                     working_dir)
+                                     None)
             }
         }
     }
@@ -1293,23 +1248,33 @@ actual:\n\
         }
     }
 
-    fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> ProcRes {
+    fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
         if !self.props.aux_builds.is_empty() {
             create_dir_all(&self.aux_output_dir_name()).unwrap();
         }
 
         let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let extra_link_args = vec!["-L".to_owned(),
-                                   aux_dir.to_str().unwrap().to_owned()];
 
         for rel_ab in &self.props.aux_builds {
             let aux_testpaths = self.compute_aux_test_paths(rel_ab);
             let aux_props = self.props.from_aux_file(&aux_testpaths.file,
                                                      self.revision,
                                                      self.config);
-            let mut crate_type = if aux_props.no_prefer_dynamic {
-                Vec::new()
+            let aux_output = {
+                let f = self.make_lib_name(&self.testpaths.file);
+                let parent = f.parent().unwrap();
+                TargetLocation::ThisDirectory(parent.to_path_buf())
+            };
+            let aux_cx = TestCx {
+                config: self.config,
+                props: &aux_props,
+                testpaths: &aux_testpaths,
+                revision: self.revision
+            };
+            let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
+
+            let crate_type = if aux_props.no_prefer_dynamic {
+                None
             } else if (self.config.target.contains("musl") && !aux_props.force_host) ||
                       self.config.target.contains("emscripten") {
                 // We primarily compile all auxiliary libraries as dynamic libraries
@@ -1321,28 +1286,20 @@ actual:\n\
                 // dynamic libraries so we just go back to building a normal library. Note,
                 // however, that for MUSL if the library is built with `force_host` then
                 // it's ok to be a dylib as the host should always support dylibs.
-                vec!["--crate-type=lib".to_owned()]
+                Some("lib")
             } else {
-                vec!["--crate-type=dylib".to_owned()]
-            };
-            crate_type.extend(extra_link_args.clone());
-            let aux_output = {
-                let f = self.make_lib_name(&self.testpaths.file);
-                let parent = f.parent().unwrap();
-                TargetLocation::ThisDirectory(parent.to_path_buf())
-            };
-            let aux_cx = TestCx {
-                config: self.config,
-                props: &aux_props,
-                testpaths: &aux_testpaths,
-                revision: self.revision
+                Some("dylib")
             };
-            let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output);
-            let auxres = aux_cx.compose_and_run(aux_args,
-                                                Vec::new(),
+
+            if let Some(crate_type) = crate_type {
+                aux_rustc.args(&["--crate-type", crate_type]);
+            }
+
+            aux_rustc.arg("-L").arg(&aux_dir);
+
+            let auxres = aux_cx.compose_and_run(aux_rustc,
                                                 aux_cx.config.compile_lib_path.to_str().unwrap(),
                                                 Some(aux_dir.to_str().unwrap()),
-                                                None,
                                                 None);
             if !auxres.status.success() {
                 self.fatal_proc_rec(
@@ -1352,40 +1309,65 @@ actual:\n\
             }
         }
 
-        self.compose_and_run(args,
-                             self.props.rustc_env.clone(),
+        rustc.envs(self.props.rustc_env.clone());
+        self.compose_and_run(rustc,
                              self.config.compile_lib_path.to_str().unwrap(),
                              Some(aux_dir.to_str().unwrap()),
-                             input,
-                             None)
+                             input)
     }
 
     fn compose_and_run(&self,
-                       ProcArgs{ args, prog }: ProcArgs,
-                       procenv: Vec<(String, String)> ,
+                       mut command: Command,
                        lib_path: &str,
                        aux_path: Option<&str>,
-                       input: Option<String>,
-                       working_dir: Option<String>) -> ProcRes {
-        self.program_output(lib_path, prog, aux_path, args, procenv, input, working_dir)
-    }
+                       input: Option<String>) -> ProcRes {
+        let cmdline =
+        {
+            let cmdline = self.make_cmdline(&command, lib_path);
+            logv(self.config, format!("executing {}", cmdline));
+            cmdline
+        };
 
-    fn make_compile_args(&self,
-                         extras: Vec<String> ,
-                         input_file: &Path,
-                         output_file: TargetLocation)
-                         -> ProcArgs
-    {
-        let target = if self.props.force_host {
-            &*self.config.host
-        } else {
-            &*self.config.target
+        command
+            .stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            .stdin(Stdio::piped());
+
+        // Need to be sure to put both the lib_path and the aux path in the dylib
+        // search path for the child.
+        let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new()))
+            .collect::<Vec<_>>();
+        if let Some(p) = aux_path {
+            path.insert(0, PathBuf::from(p))
+        }
+        path.insert(0, PathBuf::from(lib_path));
+
+        // Add the new dylib search path var
+        let newpath = env::join_paths(&path).unwrap();
+        command.env(dylib_env_var(), newpath);
+
+        let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command));
+        if let Some(input) = input {
+            child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
+        }
+        let Output { status, stdout, stderr } = child.wait_with_output().unwrap();
+
+        let result = ProcRes {
+            status,
+            stdout: String::from_utf8(stdout).unwrap(),
+            stderr: String::from_utf8(stderr).unwrap(),
+            cmdline,
         };
 
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec![input_file.to_str().unwrap().to_owned(),
-                            "-L".to_owned(),
-                            self.config.build_base.to_str().unwrap().to_owned()];
+        self.dump_output(&result.stdout, &result.stderr);
+
+        result
+    }
+
+    fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc.arg(input_file)
+            .arg("-L").arg(&self.config.build_base);
 
         // Optionally prevent default --target if specified in test compile-flags.
         let custom_target = self.props.compile_flags
@@ -1393,26 +1375,23 @@ actual:\n\
             .fold(false, |acc, x| acc || x.starts_with("--target"));
 
         if !custom_target {
-            args.extend(vec![
-                format!("--target={}", target),
-            ]);
+            let target = if self.props.force_host {
+                &*self.config.host
+            } else {
+                &*self.config.target
+            };
+
+            rustc.arg(&format!("--target={}", target));
         }
 
         if let Some(revision) = self.revision {
-            args.extend(vec![
-                "--cfg".to_string(),
-                revision.to_string(),
-            ]);
+            rustc.args(&["--cfg", revision]);
         }
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
-            args.extend(vec![
-                "-Z".to_string(),
-                format!("incremental={}", incremental_dir.display()),
-            ]);
+            rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
         }
 
-
         match self.config.mode {
             CompileFail |
             ParseFail |
@@ -1421,19 +1400,14 @@ actual:\n\
                 // fashion, then you want JSON mode. Old-skool error
                 // patterns still match the raw compiler output.
                 if self.props.error_patterns.is_empty() {
-                    args.extend(["--error-format",
-                                 "json"]
-                                .iter()
-                                .map(|s| s.to_string()));
+                    rustc.args(&["--error-format", "json"]);
                 }
             }
             MirOpt => {
-                args.extend(["-Zdump-mir=all",
-                             "-Zmir-opt-level=3",
-                             "-Zdump-mir-exclude-pass-number"]
-                            .iter()
-                            .map(|s| s.to_string()));
-
+                rustc.args(&[
+                    "-Zdump-mir=all",
+                    "-Zmir-opt-level=3",
+                    "-Zdump-mir-exclude-pass-number"]);
 
                 let mir_dump_dir = self.get_mir_dump_dir();
                 create_dir_all(mir_dump_dir.as_path()).unwrap();
@@ -1441,7 +1415,7 @@ actual:\n\
                 dir_opt.push_str(mir_dump_dir.to_str().unwrap());
                 debug!("dir_opt: {:?}", dir_opt);
 
-                args.push(dir_opt);
+                rustc.arg(dir_opt);
             }
             RunPass |
             RunFail |
@@ -1458,32 +1432,28 @@ actual:\n\
             }
         }
 
-        args.extend_from_slice(&extras);
         if !self.props.no_prefer_dynamic {
-            args.push("-C".to_owned());
-            args.push("prefer-dynamic".to_owned());
+            rustc.args(&["-C", "prefer-dynamic"]);
         }
-        let path = match output_file {
+
+        match output_file {
             TargetLocation::ThisFile(path) => {
-                args.push("-o".to_owned());
-                path
+                rustc.arg("-o").arg(path);
             }
             TargetLocation::ThisDirectory(path) => {
-                args.push("--out-dir".to_owned());
-                path
+                rustc.arg("--out-dir").arg(path);
             }
-        };
-        args.push(path.to_str().unwrap().to_owned());
+        }
+
         if self.props.force_host {
-            args.extend(self.split_maybe_args(&self.config.host_rustcflags));
+            rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
         } else {
-            args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        }
-        args.extend(self.props.compile_flags.iter().cloned());
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args: args,
+            rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
         }
+
+        rustc.args(&self.props.compile_flags);
+
+        rustc
     }
 
     fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
@@ -1532,8 +1502,8 @@ actual:\n\
 
         let prog = args.remove(0);
          ProcArgs {
-            prog: prog,
-            args: args,
+            prog,
+            args,
         }
     }
 
@@ -1554,50 +1524,12 @@ actual:\n\
         }
     }
 
-    fn program_output(&self,
-                      lib_path: &str,
-                      prog: String,
-                      aux_path: Option<&str>,
-                      args: Vec<String>,
-                      env: Vec<(String, String)>,
-                      input: Option<String>,
-                      working_dir: Option<String>)
-                      -> ProcRes {
-        let cmdline =
-        {
-            let cmdline = self.make_cmdline(lib_path,
-                                            &prog,
-                                            &args);
-            logv(self.config, format!("executing {}", cmdline));
-            cmdline
-        };
-
-        let procsrv::Result {
-            out,
-            err,
-            status
-        } = procsrv::run(lib_path,
-                         &prog,
-                         aux_path,
-                         &args,
-                         env,
-                         input,
-                         working_dir).expect(&format!("failed to exec `{}`", prog));
-        self.dump_output(&out, &err);
-        ProcRes {
-            status: status,
-            stdout: out,
-            stderr: err,
-            cmdline: cmdline,
-        }
-    }
-
-    fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String {
+    fn make_cmdline(&self, command: &Command, libpath: &str) -> String {
         use util;
 
         // Linux and mac don't require adjusting the library search path
         if cfg!(unix) {
-            format!("{} {}", prog, args.join(" "))
+            format!("{:?}", command)
         } else {
             // Build the LD_LIBRARY_PATH variable as it would be seen on the command line
             // for diagnostic purposes
@@ -1605,7 +1537,7 @@ actual:\n\
                 format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
             }
 
-            format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" "))
+            format!("{} {:?}", lib_path_cmd_prefix(libpath), command)
         }
     }
 
@@ -1723,30 +1655,22 @@ actual:\n\
 
     fn compile_test_and_save_ir(&self) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut link_args = vec!["-L".to_owned(),
-                                 aux_dir.to_str().unwrap().to_owned()];
-        let llvm_args = vec!["--emit=llvm-ir".to_owned(),];
-        link_args.extend(llvm_args);
-        let args = self.make_compile_args(link_args,
-                                          &self.testpaths.file,
-                                          TargetLocation::ThisDirectory(
-                                              self.output_base_name().parent()
-                                                                     .unwrap()
-                                                                     .to_path_buf()));
-        self.compose_and_run_compiler(args, None)
+
+        let output_file = TargetLocation::ThisDirectory(
+            self.output_base_name().parent().unwrap().to_path_buf());
+        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+        rustc.arg("-L").arg(aux_dir)
+            .arg("--emit=llvm-ir");
+
+        self.compose_and_run_compiler(rustc, None)
     }
 
     fn check_ir_with_filecheck(&self) -> ProcRes {
         let irfile = self.output_base_name().with_extension("ll");
-        let prog = self.config.llvm_filecheck.as_ref().unwrap();
-        let proc_args = ProcArgs {
-            // FIXME (#9639): This needs to handle non-utf8 paths
-            prog: prog.to_str().unwrap().to_owned(),
-            args: vec![format!("-input-file={}", irfile.to_str().unwrap()),
-                       self.testpaths.file.to_str().unwrap().to_owned()]
-        };
-        self.compose_and_run(proc_args, Vec::new(), "", None, None, None)
+        let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
+        filecheck.arg("--input-file").arg(irfile)
+            .arg(&self.testpaths.file);
+        self.compose_and_run(filecheck, "", None, None)
     }
 
     fn run_codegen_test(&self) {
@@ -2179,7 +2103,7 @@ actual:\n\
            .env("RUSTDOC",
                cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed")))
            .env("TMPDIR", &tmpdir)
-           .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var())
+           .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
            .env("LLVM_COMPONENTS", &self.config.llvm_components)
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 5d4bbd9052fe2af849a7d017b85df98ad002c20
+Subproject 25ffb3a3d7809b4fa112f3e04e926eb539dd5e9